# Gmarket KR  $1💰 URL Keyword and Review Scraper (`abotapi/gmarket-global-scraper`) Actor

Scrape product listings and customer reviews from Gmarket.co.kr into clean JSON datasets. Supports keyword search, product URLs, or review-only mode by product ID. Fast, and works on every Apify plan.

- **URL**: https://apify.com/abotapi/gmarket-global-scraper.md
- **Developed by:** [Abot API](https://apify.com/abotapi) (community)
- **Categories:** E-commerce, Developer tools, Automation
- **Stats:** 8 total users, 0 monthly users, 90.7% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $1.00 / 1,000 results

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.
Since this Actor supports Apify Store discounts, the price gets lower the higher subscription plan you have.

Learn more: https://docs.apify.com/actors/running/actors-in-store.md#pay-per-event

## What's an Apify Actor?

Actors are web data automations that power AI and operations. They run on the Apify platform to scrape websites, process data, connect APIs, and automate workflows.
In Batch mode, an Actor accepts a well-defined JSON input, performs an action which can take anything from a few seconds to a few hours,
and optionally produces a well-defined JSON output, datasets with results, or files in key-value store.
In Standby mode, an Actor provides a web server which can be used as a website, API, or an MCP server.
Actors are written with capital "A".

## How to integrate an Actor?

If asked about integration, you help developers integrate Actors into their projects.
You adapt to their stack and deliver integrations that are safe, well-documented, and production-ready.
The best way to integrate Actors is as follows.

- **AI agents and MCP clients** — the [Apify MCP server](https://docs.apify.com/integrations/mcp.md) at `https://mcp.apify.com` (remote, streamable HTTP, OAuth on first use).
- **Agentic workflows and local Actor development** — [Agent Skills](https://apify.com/.well-known/agent-skills/index.json) with the [Apify CLI](https://docs.apify.com/cli/docs.md): `npm install -g apify-cli`, then `apify login`.
- **JavaScript/TypeScript projects** — the official [JS/TS client](https://docs.apify.com/api/client/js/docs.md): `npm install apify-client`.
- **Python projects** — the official [Python client](https://docs.apify.com/api/client/python/docs.md): `pip install apify-client`.
- **Any other language** — the [REST API](https://docs.apify.com/api/v2.md).

For usage examples, see the [API](#api) section below.

For more details, see Apify documentation as [Markdown index](https://docs.apify.com/llms.txt) and [Markdown full-text](https://docs.apify.com/llms-full.txt).

# README

## Gmarket Global Scraper

> Sample shape below is illustrative; values are placeholders, not from a live listing.

Pull product listings AND customer reviews from Gmarket Global (the English-language storefront of one of Korea's biggest marketplaces) into a clean JSON dataset. Two modes: keyword search or URL paste. One toggle flips the same flow from "one record per product" to "one record per review." Detail enrichment is on by default and adds the full seller disclosure (business name, manager, customer-service phone, business registration, e-commerce registration).

### Why this scraper

- 25+ product fields per record, with optional detail enrichment that adds the legally-mandated Korean seller info (company name, manager name, customer-service phone, business registration number, e-commerce sales registration).
- Flip "Reviews only" to scrape reviews of every matching product instead of the products themselves.
- English titles by default (the global storefront serves English).
- KRW and USD prices side by side, plus original-vs-sale price and discount percent.
- Every record also carries a `raw` block with the verbatim upstream API response, so no field is ever silently dropped.
- Datacenter proxy works out of the box on the free Apify plan.

### Data you get

#### Product records (default)

| Field | Example |
| --- | --- |
| goodsCode | "0000000001" |
| title | "Sample Product Title" |
| linkUrl | "https://mg.gmarket.co.kr/Item?goodscode=0000000001" |
| imageUrl | "https://gdimg.gmarket.co.kr/0000000001/still/280?ver=0" |
| additionalImages | \["https://gdimg.gmarket.co.kr/.../shop/_img/000/000/0000000001.jpg"] |
| sellPriceKrw | 22800 |
| originalPriceKrw | "22,800" |
| salePriceKrw | "22,800" |
| currencyPrice | "$15.75" |
| discountRate | "0" |
| wasPriceKrw | 41490 (numeric, `null` when not on special) |
| currentPriceKrw | 22800 (numeric current/paying price, always populated) |
| savingsAmountKrw | 5200 (numeric, `null` when not on special) |
| discountRatePercent | 21 (numeric mirror of `discountRate`, `null` when not on special) |
| isOnSpecial | false |
| isBigSmilePromo | false (correctly wired from the API's `IsBigSmileItem`; see note below) |
| bigSmileImageUrl | null |
| isSponsored | false |
| isFreeShipping | true |
| deliveryInfo | "Free" |
| deliveryFee | "0" |
| sellerCustNo | "000000000" |
| miniShopHandle | "samplestore" |
| miniShopUrl | "https://mg.gmarket.co.kr/samplestore" |
| categoryCodeL | "100000000" |
| categoryCodeM | "200000000" |
| categoryCodeS | "300000000" |
| overseaDeliveryAvailable | true |
| isBigSmile | false |
| isAdult | false |
| translation.english | true |
| translation.chinese | true |
| translation.japanese | false |
| raw | `{ ...full upstream Item JSON... }` |
| scrapedAt | "2026-01-01T00:00:00.000Z" |

When `fetchDetails` is on (the default), each record also carries:

| Field | Example |
| --- | --- |
| descriptionText | "Up to 3,000 chars of cleaned product description." |
| brand | "SampleBrand" |
| sellerCompanyName | "Sample Trading Co., Ltd." |
| sellerManagerName | "John Doe" |
| sellerPhone | "02-0000-0000" |
| sellerBusinessNumber | "000-00-00000" |
| sellerEcommerceNumber | "0000-Seoul-0000" |
| sellerInfo | `{ ...full upstream SellerInfo JSON: 15 fields... }` |

### Specials, was-price & discount

Every product already carries a genuine, per-product was/current price and discount rate (verified
live, never fabricated): a was price, a current price, and the site's own computed discount % plus the
exact KRW savings. The numeric fields below are additive and derived from data the scrape already
collects for each product, so they add no extra work and no extra cost:

- `wasPriceKrw` / `savingsAmountKrw` / `discountRatePercent` populate **only when the item is genuinely
  discounted** (mirrors the existing `discountRate` field); on an ordinary, non-discounted item they are
  `null` — verified live on a `laptop` search (all `0` in `discountRate`, `wasPriceKrw`/`savingsAmountKrw`
  correctly `null`).
- `currentPriceKrw` is the numeric price the customer actually pays right now (parsed `SalePrice`); it is
  always populated, discounted or not.
- Verified live on a `phone case` search (majority of cards discounted): e.g. was ₩24,000 → now ₩18,800,
  save ₩5,200 (21%); was ₩10,000 → now ₩6,900, save ₩3,100 (31%) — matching the site's own math exactly.

**Specials-category taxonomy — verified, not fabricated.** Gmarket Global was checked directly for any
Super Deals / Big Sale / discount-collection surface **beyond** what's already scraped. None exists:

- Sort options are only relevance/popularity, newest, price asc/desc, and rating — no discount- or
  deal-based sort.
- There is no separate deals/specials collection or category to browse; the only promotion-scoped
  filter is the sitewide "BigSmile" promotion, which this actor **already** exposes as the
  `bigSmileOnly` input (default off — this already satisfies "specials as an opt-in, never auto-run").
- `isBigSmilePromo` and `bigSmileImageUrl` are additive fields that correctly reflect a product's real
  BigSmile promotion status (the pre-existing `isBigSmile` output field reads a differently-named key
  that never carries a value, so it is always `false`; left unchanged to avoid revaluing an existing
  field — `isBigSmilePromo` is the accurate signal going forward). `isSponsored` is an additional real,
  non-fabricated per-product signal (sponsored/ad placement).
- BigSmile campaigns are time/keyword-gated — across several unrelated keyword probes during
  verification, `isBigSmilePromo=true` returned 0 items each time. The fields still populate correctly
  whenever a live BigSmile campaign covers the searched keyword; they are not fabricated when it doesn't.

#### Review records (when `reviewsOnly` is on)

The actor still uses your keyword or URL input to discover products, but pushes one record per review instead of one per product.

| Field | Example |
| --- | --- |
| productGoodsCode | "0000000001" |
| productLinkUrl | "https://mg.gmarket.co.kr/Item?goodscode=0000000001" |
| reviewId | "100000000" |
| authorNickname | "abc\*\*\*\*" (Gmarket-masked) |
| authorLoginId | "abc1234" (the un-masked login, passed through verbatim) |
| authorCustNo | "0000000000" |
| authorCountryCode | "KR" |
| rating | 9 |
| ratingMax | 10 |
| deliveryRating | 5 |
| title | "Sample review title" |
| comment | "Sample comment body" |
| titleEnglish | "Sample title translated" |
| commentEnglish | "Sample comment translated" |
| reviewDate | "2026-01-01T00:00:00.000Z" |
| reviewDateText | "2026.01.01" |
| hasPhotos | true |
| photoUrls | \["https://bampic.gmarket.co.kr/..."] |
| variantInfo | "Color: Black \[1ea]" |
| sellerReply | null |
| sellerReplyDate | null |
| isPowerReviewer | true |
| readCount | 0 |
| raw | `{ ...full upstream review JSON, 40 fields... }` |
| scrapedAt | "2026-01-01T00:00:00.000Z" |

### How to use

Keyword search, default settings (detail enrichment on, unlimited pages capped at 20 records by `maxListings`):

```json
{
  "mode": "search",
  "keywords": ["laptop"]
}
```

Keyword search with price band, oversea-only, multi-keyword, deeper pagination:

```json
{
  "mode": "search",
  "keywords": ["headphones", "earbuds"],
  "minPrice": 10000,
  "maxPrice": 100000,
  "overseaDeliveryOnly": true,
  "maxPages": 3
}
```

URL mode (paste any Gmarket Global search URL with whatever filters you want):

```json
{
  "mode": "url",
  "urls": ["https://mg.gmarket.co.kr/Search/Search?keyword=phone&minPrice=50000&maxPrice=500000"],
  "maxPages": 2
}
```

Reviews only (pulls reviews of every product matching your search; caps total reviews at maxListings):

```json
{
  "mode": "search",
  "keywords": ["laptop"],
  "reviewsOnly": true,
  "maxReviewsPerProduct": 20,
  "maxListings": 100
}
```

### Input parameters

| Parameter | Type | Default | Description |
| --- | --- | --- | --- |
| mode | enum | "search" | "search" uses keywords + filters; "url" uses pasted search-result URLs |
| keywords | array of strings | \["laptop"] | One or more product keywords; English or Korean both work. Search mode only |
| minPrice | integer | 0 | Min sale price in KRW. 0 = no minimum |
| maxPrice | integer | 0 | Max sale price in KRW. 0 = no maximum |
| overseaDeliveryOnly | boolean | false | Restrict to items that ship outside Korea |
| bigSmileOnly | boolean | false | Restrict to BigSmile sitewide promotion items |
| urls | array of strings | \[...] | One entry per search. URL mode only |
| reviewsOnly | boolean | false | Push one record per review instead of one per product. Uses the same search/URL flow to discover products first |
| maxReviewsPerProduct | integer | 50 | Reviews-only mode: stop after N reviews per product (20 per page) |
| maxPages | integer | 0 | Pages to walk per keyword / URL (60 items per page). 0 = unlimited — walk all pages until the site runs out of results |
| maxListings | integer | 20 | Cap on TOTAL records output (products or reviews depending on `reviewsOnly`). Keeps a default run small; set 0 to walk the entire catalogue (unlimited) |
| fetchDetails | boolean | true | Fetch product detail pages to populate description, brand, and the full seller disclosure. Turn off for a leaner, faster scrape |
| resumeFromRunId | string | (empty) | Paste a previous run ID or dataset ID to continue a large walk-all pull: products/reviews already saved by that run are loaded before scraping starts and skipped, so this run only appends new records |
| incrementalMode | boolean | false | Recurring monitoring of the same search — see "Resume & recurring updates" below |
| stateKey | string | (empty) | Incremental mode only. Override the auto-derived search-scope key |
| emitUnchanged | boolean | false | Incremental mode only. Push (and bill) UNCHANGED records too, not just the delta |
| emitExpired | boolean | false | Incremental mode only. Push (and bill) a tombstone row for records that disappeared, after a complete scan |
| proxy | proxy | Apify Datacenter | Network. Datacenter works fine; residential rarely needed |

### Resume & recurring updates

Two distinct features, both under the "Resume & recurring updates" input section:

- **`resumeFromRunId`** continues ONE interrupted walk-all pull: paste a previous run/dataset id and
  this run skips every `goodsCode`/`reviewId` already saved there.
- **`incrementalMode`** (default off) is for scheduling this actor daily/weekly against the SAME
  search. The actor remembers the last run's products (or reviews, if `reviewsOnly` is on) itself, in a
  key-value store keyed by your search scope (mode, keywords/URLs, price range, `overseaDeliveryOnly`,
  `bigSmileOnly`, `reviewsOnly`, `fetchDetails` — override with `stateKey` to track multiple schedules
  explicitly). Every pushed record gets a `changeType`: `NEW`, `UPDATED`, `UNCHANGED`, `REAPPEARED`, or
  `EXPIRED`, plus `changedFields`, `firstSeenAt`, `lastSeenAt`.
  - By default only `NEW`/`UPDATED`/`REAPPEARED` are pushed and billed — a quiet run with nothing
    changed pushes (and charges) nothing. Turn on `emitUnchanged` to get a full snapshot every run
    instead of just the delta.
  - `emitExpired` (default off) additionally pushes a tombstone row for anything that dropped out of
    the results — only after a run that scanned the **complete** tracked search; a capped, resumed, or
    partial run never marks anything expired.
  - Products and reviews are tracked in **separate namespaces internally** — a product id and a review
    id can never collide, and a new review never makes its parent product look `UPDATED` (the two are
    unrelated fields on unrelated records).
  - **What counts as a change, and what's deliberately excluded from that comparison (verified live,
    2026-08-05):** two immediate re-fetches of the same search returned byte-identical product data —
    price, images, category — for all 60 compared products. The one field that DOES change on every
    independent fetch is `sellerInfo.EncodedCustNo` (only present when `fetchDetails` is on): it's a
    per-request encoded token wrapping the same seller identity, not a real business-data change — every
    other seller field (company name, registration number, manager, CS phone) stayed byte-identical
    across fetches, and the plain `sellerCustNo` field is unaffected. It's excluded from change detection
    but still present verbatim inside `sellerInfo` in every pushed record. For reviews, `readCount` (the
    review's view counter) is likewise excluded from the comparison — it climbs on its own regardless of
    whether the review's actual content changed — but it is still always present in the output; only the
    change-detection ignores it. A detail-page fetch that fails transiently (or a product that genuinely
    has no description) also never counts as a change by itself — only a real value-to-different-value
    edit does.

### Send results into your apps (MCP connectors)

Optionally pipe the scraped results into the apps you already use, via Model Context Protocol (MCP) connectors. This is an extra delivery step **after** the scrape — the Apify dataset is never changed.

**What gets written to the connector:** a condensed, human-readable **summary** of each record — not the full JSON. Each item becomes one entry with a **title** and its key fields flattened to plain text. The **complete record always stays in the Apify dataset**.

1. Authorize a connector once under **Apify → Settings → Integrations** (Notion, Linear, Airtable, or Apify).
2. Select it in the **"Pipe results into your apps"** input field. (If the picker is empty, you haven't authorized a connector yet.)
3. For **Notion**, also set `notionParentPageUrl` to the page where items should be created.

The connection is mediated by Apify's MCP proxy, so this actor never sees your third-party credentials. Leave the field empty to skip.

### Output example (product, with fetchDetails: true)

```json
{
  "goodsCode": "0000000001",
  "title": "Sample Product Title",
  "linkUrl": "https://mg.gmarket.co.kr/Item?goodscode=0000000001",
  "imageUrl": "https://gdimg.gmarket.co.kr/0000000001/still/280?ver=0",
  "sellPriceKrw": 22800,
  "currencyPrice": "$15.75",
  "discountRate": "0",
  "wasPriceKrw": null,
  "currentPriceKrw": 22800,
  "savingsAmountKrw": null,
  "discountRatePercent": null,
  "isOnSpecial": false,
  "isBigSmilePromo": false,
  "bigSmileImageUrl": null,
  "isSponsored": false,
  "sellerCompanyName": "Sample Trading Co., Ltd.",
  "sellerManagerName": "John Doe",
  "sellerPhone": "02-0000-0000",
  "sellerBusinessNumber": "000-00-00000",
  "sellerEcommerceNumber": "0000-Seoul-0000",
  "sellerInfo": {
    "CompanyName": "Sample Trading Co., Ltd.",
    "ManagerName": "John Doe",
    "HelpDeskStartDate": "10",
    "HelpDeskEndDate": "16",
    "HelpDeskTelNo": "02-0000-0000",
    "CompanyNo": "000-00-00000",
    "EcomerceNo": "0000-Seoul-0000",
    "SellerGrade": "A1",
    "DealerSatisGrade": "AA"
  },
  "descriptionText": "Sample product description text.",
  "brand": "SampleBrand",
  "overseaDeliveryAvailable": true,
  "translation": { "english": true, "chinese": true, "japanese": false },
  "scrapedAt": "2026-01-01T00:00:00.000Z"
}
```

### Plan requirement

Works on any Apify plan, including the Free plan, because the default proxy is Apify Datacenter. If you ever see zero results from Apify Datacenter, switch the proxy to Apify Residential (Starter plan or higher) and try again.

# Actor input Schema

## `mode` (type: `string`):

Pick how you want to drive the scrape. 'Keyword search' uses your keywords + filters; 'Paste URLs' uses Gmarket Global search-result URLs you already have.

## `keywords` (type: `array`):

One or more product keywords to search for (English or Korean both work). One run = one search per keyword × applied filters. Only used when mode is 'Keyword search'.

## `minPrice` (type: `integer`):

Minimum sale price in Korean Won. Leave 0 for no minimum. Example: 10000 (≈ $7 USD).

## `maxPrice` (type: `integer`):

Maximum sale price in Korean Won. Leave 0 for no maximum. Example: 100000 (≈ $70 USD).

## `overseaDeliveryOnly` (type: `boolean`):

When on, returns only items that ship outside Korea. Verified to narrow results by ~75% on broad queries.

## `bigSmileOnly` (type: `boolean`):

When on, returns only items participating in the BigSmile sitewide promotion.

## `urls` (type: `array`):

One or more Gmarket Global search-result URLs (must contain /Search/Search?keyword=...). Filter fields above are ignored in this mode; the URL's own query parameters are the filters. Forward pagination starts from the page in the URL.

## `reviewsOnly` (type: `boolean`):

When on, the actor still uses your keyword search or pasted URLs to discover products, but pushes one record per REVIEW instead of one record per product. Pair with maxReviewsPerProduct to cap how deep to walk each product.

## `maxReviewsPerProduct` (type: `integer`):

Only applies when 'Reviews only' is on. Stop after this many reviews per product. The API serves 20 per page; 50 = up to 3 pages each. Set 0 to walk every review the product has. Reviews come back in Gmarket's default order (typically featured first; the storefront does not expose a sort control).

## `maxPages` (type: `integer`):

How many pages to walk per keyword (or per URL). The API serves 60 items per page, so 1 page returns up to 60 products. 0 = unlimited (walk all pages until the site runs out of results).

## `maxListings` (type: `integer`):

Stop the whole run once this many unique records have been collected. When 'Reviews only' is off this counts products; when on it counts reviews across all products. Default 20 keeps a run small; set 0 to walk the entire catalogue (unlimited).

## `fetchDetails` (type: `boolean`):

When on, makes one extra fetch per item to capture description text, brand, and full seller info (company name, manager, customer-service phone, business number, e-commerce sales registration). Turn off for a faster, leaner scrape with only the search-listing fields.

## `resumeFromRunId` (type: `string`):

Optional. Paste a previous run ID or dataset ID to continue a large walk-all pull: products/reviews already saved by that run are loaded before scraping starts and skipped, so this run only appends new records. Leave empty for a normal fresh run. Combine with 'Incremental mode' only to bootstrap a brand-new recurring monitor from a completed walk-all pull — if this search already has saved incremental state, the run fails fast instead of silently starting a second, overlapping baseline.

## `incrementalMode` (type: `boolean`):

When on, the actor remembers the products (or reviews, if 'Reviews only' is on) from the last run of this SAME search and only pushes what's NEW, UPDATED, or REAPPEARED since then — a different workflow from 'Resume from a prior run' above, which continues one specific interrupted run instead of remembering a search across scheduled runs. Every pushed record gets a `changeType` field. Off by default so a plain run behaves exactly as before.

## `stateKey` (type: `string`):

Only used when 'Incremental mode' is on. Leave empty to auto-derive the tracked search from your mode/keywords/URLs/price range/'Reviews only'/'Fetch detail pages' settings (raising maxListings or maxPages does not start a new baseline). Set your own text here to track multiple schedules explicitly, or to keep the baseline stable even if you plan to change a filter later.

## `emitUnchanged` (type: `boolean`):

Only used when 'Incremental mode' is on. Off by default: a record that hasn't changed since the last run is neither pushed nor billed. Turn this on to also push (and pay for) every UNCHANGED record every run — useful if you want a complete snapshot each time instead of only the delta.

## `emitExpired` (type: `boolean`):

Only used when 'Incremental mode' is on. Off by default. Turn this on to push (and pay for) an EXPIRED row for any previously-tracked product/review that no longer appears — only fires after a run that completed a full scan of the tracked search (a capped, resumed, or partial run never marks anything expired, since it can't tell 'gone' apart from 'not reached yet').

## `proxy` (type: `object`):

Apify Datacenter is the default and is free-tier compatible. Residential is rarely needed for this site.

## `mcpConnectors` (type: `array`):

Optionally send the scraped results into the apps you already use, via Model Context Protocol (MCP) connectors. Authorize a connector once under Apify → Settings → Integrations, then select it here. The connector receives a condensed, human-readable summary per item (title + key fields), not the full JSON — the complete record stays in the dataset. Leave empty to skip. Supported: Notion (https://mcp.notion.com/mcp), Linear (https://mcp.linear.app/sse), Airtable (https://mcp.airtable.com/mcp), Apify (https://mcp.apify.com).

## `notionParentPageUrl` (type: `string`):

URL (or id) of the Notion page under which item pages are created. Required to enable the Notion export; ignored by other connectors.

## `maxNotifyListings` (type: `integer`):

Cap on items written to each connector per run. Does not affect the dataset.

## Actor input object example

```json
{
  "mode": "search",
  "keywords": [
    "laptop"
  ],
  "minPrice": 0,
  "maxPrice": 0,
  "overseaDeliveryOnly": false,
  "bigSmileOnly": false,
  "urls": [
    "https://mg.gmarket.co.kr/Search/Search?keyword=laptop"
  ],
  "reviewsOnly": false,
  "maxReviewsPerProduct": 50,
  "maxPages": 0,
  "maxListings": 20,
  "fetchDetails": true,
  "incrementalMode": false,
  "emitUnchanged": false,
  "emitExpired": false,
  "proxy": {
    "useApifyProxy": true
  },
  "maxNotifyListings": 50
}
```

# Actor output Schema

## `overview` (type: `string`):

No description

## `reviews` (type: `string`):

No description

# API

You can run this Actor programmatically using our API. Below are code examples in JavaScript, Python, and CLI, as well as the OpenAPI specification and MCP server setup.

## JavaScript example

```javascript
import { ApifyClient } from 'apify-client';

// Initialize the ApifyClient with your Apify API token
// Replace the '<YOUR_API_TOKEN>' with your token
const client = new ApifyClient({
    token: '<YOUR_API_TOKEN>',
});

// Prepare Actor input
const input = {
    "keywords": [
        "laptop"
    ],
    "urls": [
        "https://mg.gmarket.co.kr/Search/Search?keyword=laptop"
    ],
    "proxy": {
        "useApifyProxy": true
    }
};

// Run the Actor and wait for it to finish
const run = await client.actor("abotapi/gmarket-global-scraper").call(input);

// Fetch and print Actor results from the run's dataset (if any)
console.log('Results from dataset');
console.log(`💾 Check your data here: https://console.apify.com/storage/datasets/${run.defaultDatasetId}`);
const { items } = await client.dataset(run.defaultDatasetId).listItems();
items.forEach((item) => {
    console.dir(item);
});

// 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/js/docs

```

## Python example

```python
from apify_client import ApifyClient

# Initialize the ApifyClient with your Apify API token
# Replace '<YOUR_API_TOKEN>' with your token.
client = ApifyClient("<YOUR_API_TOKEN>")

# Prepare the Actor input
run_input = {
    "keywords": ["laptop"],
    "urls": ["https://mg.gmarket.co.kr/Search/Search?keyword=laptop"],
    "proxy": { "useApifyProxy": True },
}

# Run the Actor and wait for it to finish
run = client.actor("abotapi/gmarket-global-scraper").call(run_input=run_input)

# Fetch and print Actor results from the run's dataset (if there are any)
print(f"💾 Check your data here: https://console.apify.com/storage/datasets/{run.default_dataset_id}")
for item in client.dataset(run.default_dataset_id).iterate_items():
    print(item)

# 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/python/docs/quick-start

```

## CLI example

```bash
echo '{
  "keywords": [
    "laptop"
  ],
  "urls": [
    "https://mg.gmarket.co.kr/Search/Search?keyword=laptop"
  ],
  "proxy": {
    "useApifyProxy": true
  }
}' |
apify call abotapi/gmarket-global-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,abotapi/gmarket-global-scraper"
        }
    }
}

```

The hosted server signs you in with OAuth on first connect, so no API token belongs in this config. Clients without OAuth support can send an `Authorization: Bearer <APIFY_API_TOKEN>` header instead, using a token from API & Integrations in Apify Console (https://console.apify.com/settings/integrations).

## OpenAPI specification

Download the OpenAPI definition: https://api.apify.com/v2/actors/kenHH2gL6JIDgkXMi/builds/ME4UtQIQcajz4x736/openapi.json
