# Shopee Product Details Scraper (`automation-lab/shopee-product-details-scraper`) Actor

Extract public Shopee product details from URLs or IDs across eight country storefronts, including descriptions, media, attributes, variants, stock, seller context, and price, sales, or rating signals when exposed.

- **URL**: https://apify.com/automation-lab/shopee-product-details-scraper.md
- **Developed by:** [Stas Persiianenko](https://apify.com/automation-lab) (community)
- **Categories:** E-commerce
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

Pay per event

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/platform/actors/running/actors-in-store#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

## Shopee Product Details Scraper

Extract structured public Shopee product details from product URLs or shop ID/item ID pairs.
The Actor is designed for recurring catalog monitoring across Shopee Singapore, Malaysia,
Indonesia, Thailand, Philippines, Vietnam, Brazil, and Mexico.

It returns one normalized product record per successful input, including product identity,
description, media, attributes, category path, seller context, availability, visible stock,
and variants. Price, sales, likes, and rating signals are included when Shopee exposes them
in the public product response; these fields can be `null`.

### What does this Shopee scraper do?

The Actor accepts a focused list of products instead of crawling broad search results.
For each supplied product it:

1. identifies the country storefront, shop ID, and item ID;
2. opens the product through a country-matched residential session;
3. reads Shopee's server-rendered product state;
4. validates that the returned item matches the requested item ID;
5. normalizes product, variant, seller, stock, media, and conditional price signals;
6. stores one JSON record in the default dataset.

This makes the output suitable for scheduled comparisons, spreadsheets, databases,
BI tools, data pipelines, and catalog-quality checks.

### Who is it for?

- **Marketplace analysts** tracking selected Shopee assortment and availability.
- **Brands and distributors** checking how public product content changes by storefront.
- **Catalog teams** collecting titles, descriptions, images, specifications, and variants.
- **Pricing teams** recording public price fields when Shopee makes them available.
- **Developers** needing a normalized Shopee API-style dataset from URLs or IDs.
- **Sourcing teams** comparing visible variant labels, stock, seller, and category context.

The Actor is not a broad keyword-search crawler and does not require a Shopee account.

### Supported Shopee storefronts

| Country | Country code | Domain |
|---|---:|---|
| Singapore | `SG` | `shopee.sg` |
| Malaysia | `MY` | `shopee.com.my` |
| Indonesia | `ID` | `shopee.co.id` |
| Thailand | `TH` | `shopee.co.th` |
| Philippines | `PH` | `shopee.ph` |
| Vietnam | `VN` | `shopee.vn` |
| Brazil | `BR` | `shopee.com.br` |
| Mexico | `MX` | `shopee.com.mx` |

Product URLs automatically select their storefront. ID-only inputs can include a country
prefix, for example `id:196846900:11089699432`.

### What Shopee data can you extract?

| Field group | Examples | Availability |
|---|---|---|
| Identity | item ID, shop ID, title, canonical URL, country | Expected for successful products |
| Content | description, brand, category path, attributes | When present on the public page |
| Media | image URLs and video URLs | When exposed |
| Availability | normalized status and visible stock | When public product state exposes it |
| Variants | model ID, name, stock, availability, conditional price | When the product has models/SKUs |
| Seller | shop ID, public name, location, official/preferred flags, logo | When exposed |
| Commerce | currency, price range, previous price, discount | Conditional; can be `null` |
| Engagement | sold, rating, rating count, likes | Conditional; can be `null` |
| Audit | source URL and scrape timestamp | Included in every successful row |

A `null` value means the field was not exposed in the public response used for that run.
The Actor does not invent or infer hidden prices, ratings, or sales.

### How to run the Actor

1. Open the Actor input page.
2. Add one or more public Shopee product URLs under **Shopee product URLs**.
3. Optionally add `shopId:itemId` or `country:shopId:itemId` entries.
4. Set **Maximum products** to bound the run.
5. Leave retries at the default unless you need a stricter runtime bound.
6. Click **Start**.
7. Open the **Shopee products** dataset view when the run finishes.
8. Export the rows as JSON, CSV, Excel, XML, or RSS, or fetch them through the API.

The prefilled Singapore product URL is a real supported input and is suitable for a first run.

### Input parameters

| Parameter | Type | Default | Description |
|---|---|---:|---|
| `startUrls` | array | example product | Shopee product URLs in `-i.shopId.itemId` or `/product/shopId/itemId` form |
| `productIds` | string array | none | `shopId:itemId` or `country:shopId:itemId` entries |
| `countryCode` | string | `SG` | Storefront for ID entries without a country prefix |
| `maxItems` | integer | `20` | Maximum unique products, from 1 to 500 |
| `maxRetries` | integer | `2` | Fresh residential retries after a transient or incomplete response, from 0 to 3 |

At least one URL or ID is required. Duplicate products are processed once.
Unsupported domains and malformed IDs fail before any product is fetched.

### Input examples

Extract one Singapore product by URL:

```json
{
  "startUrls": [
    { "url": "https://shopee.sg/product-i.131198971.6646421738" }
  ],
  "maxItems": 1
}
```

Extract one Shopee Indonesia product by IDs:

```json
{
  "productIds": ["id:196846900:11089699432"],
  "maxItems": 1
}
```

Use the default country for several ID pairs:

```json
{
  "countryCode": "SG",
  "productIds": [
    "131198971:6646421738",
    "1120328630:29972859686"
  ],
  "maxItems": 2
}
```

### Output example

The following shortened example reflects current output shape. Public values vary by item
and run, and conditional fields may be `null`.

```json
{
  "itemId": "6646421738",
  "shopId": "131198971",
  "countryCode": "SG",
  "canonicalUrl": "https://shopee.sg/product/131198971/6646421738",
  "title": "Baseus WM01 TWS Bluetooth Earphones...",
  "brand": "BASEUS",
  "currency": "SGD",
  "price": null,
  "availability": "available",
  "stock": 100,
  "rating": null,
  "categoryPath": ["Mobile & Gadgets", "Audio", "Earphones"],
  "imageUrls": [
    "https://down-sg.img.susercontent.com/file/cn-11134207-7r98o-lt3ijo9b9xwde3"
  ],
  "attributes": [
    { "name": "Connection Type", "value": "Wireless" }
  ],
  "variants": [
    {
      "id": "198131699565",
      "name": "Pink",
      "stock": 10,
      "price": null,
      "isAvailable": true
    }
  ],
  "seller": {
    "id": "131198971",
    "name": "Baseus Official Store",
    "location": "SG",
    "isOfficial": true
  },
  "scrapedAt": "2025-01-15T12:00:00.000Z"
}
```

### Understanding prices and null fields

Shopee can vary public product fields by country, session, item, and time.
The Actor exports price fields only when they are present in the public server response.
It does not log in, place items in a cart, choose a delivery address, or estimate a price.

For monitoring, compare `price`, `priceMin`, `priceMax`, and variant prices only when both
snapshots contain values. Keep the currency and country code with every comparison.

The same rule applies to rating, rating count, sold count, likes, seller name, and seller flags.
A missing field is represented as `null`, not zero.

### How much does it cost to extract Shopee product details?

The Actor uses pay-per-event pricing:

- a **$0.005 start event** is charged once per valid run;
- the BRONZE tier is **$0.016 per successfully delivered product**;
- failed, duplicate, malformed, or undelivered products do not receive an item event charge.

Example BRONZE event charges:

| Delivered products | Start | Product events | Total event price |
|---:|---:|---:|---:|
| 1 | $0.005 | $0.016 | $0.021 |
| 10 | $0.005 | $0.160 | $0.165 |
| 100 | $0.005 | $1.600 | $1.605 |

Apify applies lower per-product rates at higher account tiers. Platform usage and any account
limits are shown by Apify before and during the run. Check the Actor pricing tab for your
active tier.

### Catalog and stock monitoring workflow

A repeatable monitoring setup looks like this:

1. Keep a stable list of product URLs or country-qualified IDs.
2. Create an Apify Task using that input.
3. Schedule the Task at the interval appropriate for your business.
4. Save each dataset with `scrapedAt`, `itemId`, `countryCode`, and `currency`.
5. Join snapshots on country, shop ID, item ID, and variant ID.
6. Alert only on fields that were present in both compared snapshots.
7. Treat a run failure as missing evidence, not as an out-of-stock event.

This avoids confusing a blocked or incomplete response with a real catalog change.

### Export and integration options

You can use the default dataset with:

- JSON or JSONL ingestion pipelines;
- CSV and Excel exports for analysts;
- Google Sheets through Apify integrations;
- webhooks triggered when a run succeeds or fails;
- Make, Zapier, and custom automation;
- scheduled Tasks for recurring product snapshots;
- database loaders keyed by country, shop ID, item ID, and scrape time.

Arrays such as `variants`, `attributes`, and `imageUrls` remain nested in JSON. Flatten them
in your destination only when your reporting model requires it.

### Use the Shopee scraper API with cURL

Start a run synchronously and receive dataset items:

```bash
curl -X POST \
  "https://api.apify.com/v2/acts/automation-lab~shopee-product-details-scraper/run-sync-get-dataset-items?token=$APIFY_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "startUrls": [
      {"url": "https://shopee.sg/product-i.131198971.6646421738"}
    ],
    "maxItems": 1
  }'
```

For production systems, keep the token in an environment variable or secret manager.
Do not commit it to source control.

### Use the API with JavaScript

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

const client = new ApifyClient({ token: process.env.APIFY_TOKEN });

const run = await client.actor('automation-lab/shopee-product-details-scraper').call({
  productIds: ['id:196846900:11089699432'],
  maxItems: 1,
});

const { items } = await client.dataset(run.defaultDatasetId).listItems();
console.log(items[0]);
```

The asynchronous `call` method lets you inspect run status, usage, and dataset metadata.

### Use the API with Python

```python
import os
from apify_client import ApifyClient

client = ApifyClient(os.environ['APIFY_TOKEN'])
run = client.actor('automation-lab/shopee-product-details-scraper').call(run_input={
    'startUrls': [
        {'url': 'https://shopee.sg/product-i.131198971.6646421738'}
    ],
    'maxItems': 1,
})

items = client.dataset(run['defaultDatasetId']).list_items().items
print(items[0])
```

### Use with Apify MCP

Add the Actor to Claude Code:

```bash
claude mcp add --transport http apify \
  "https://mcp.apify.com?tools=automation-lab/shopee-product-details-scraper"
```

**Claude Desktop setup**

Add the following server configuration in Claude Desktop. The same HTTP MCP server can also be used by editor clients.

```json
{
  "mcpServers": {
    "apify": {
      "url": "https://mcp.apify.com?tools=automation-lab/shopee-product-details-scraper"
    }
  }
}
```

**Cursor setup:** add the same `apify` server URL to Cursor's MCP settings.

**VS Code setup:** add the same HTTP server URL to the MCP configuration used by your VS Code AI extension.

Example prompts:

- "Extract this Shopee Singapore product and summarize its visible variants and stock."
- "Fetch these Shopee Indonesia product IDs and return a table of brands and categories."
- "Compare these two scheduled Shopee datasets and flag variant availability changes."

### Reliability and failure behavior

Shopee applies traffic controls and can vary data by geography. The Actor therefore uses a
residential proxy matched to the product storefront and a sticky identity for each attempt.
It downloads only the initial product document and blocks scripts, images, fonts, video,
analytics, and other unnecessary browser resources.

A product is saved only when the structured response contains the requested item ID.
A blocked, incomplete, mismatched, or malformed response is retried with a fresh identity up
to `maxRetries`. If every product fails, the Actor fails with a non-zero run status.
If some products succeed, those records are delivered and individual failures are logged.

### Limits and troubleshooting

#### Why is a price or rating field null?

Shopee did not expose that field in the public product response used for the run. This is an
expected source limitation. The Actor does not infer private or location-dependent values.

#### Why did a product fail?

Check that the URL is public, belongs to a supported country domain, and includes the shop ID
and item ID. Deleted, region-restricted, adult-gated, or challenged products may not return a
usable public record. A retry can recover transient blocks but cannot make private data public.

#### Can I enter a short link?

Use a final Shopee product URL containing `-i.shopId.itemId` or `/product/shopId/itemId`.
Short redirect links are not accepted because they do not identify the storefront and product
before the country-matched session is created.

#### Does it scrape reviews?

No. The output includes public aggregate rating signals when exposed, but it does not paginate
individual review text. This keeps the product focused on product-detail and catalog snapshots.

#### Does it support search keywords or shop crawling?

No. Supply exact product URLs or IDs. Broad discovery, keyword search, and full-shop crawling
are outside this Actor's scope.

### Responsible use and legality

Use the Actor only for lawful purposes and public information you are permitted to process.
Respect Shopee's terms, applicable database and copyright rights, privacy law, rate limits,
and the rights of sellers and buyers. Do not use the output to profile individuals, evade
access controls, or collect private account data.

You are responsible for choosing an appropriate schedule, retention period, and lawful basis.
The Actor does not log in and does not request buyer-private or seller-private information.

### Related automation-lab Actors

- [Lazada Products, Sellers & Reviews Scraper](https://apify.com/automation-lab/lazada-products-scraper)
  for a related Southeast Asia marketplace workflow.
- [Tokopedia Products, Sellers and Reviews Monitor](https://apify.com/automation-lab/tokopedia-products-sellers-monitor)
  for Indonesian marketplace assortment and seller monitoring.
- [AliExpress Products & Seller Catalog Scraper](https://apify.com/automation-lab/aliexpress-products-scraper)
  for global marketplace catalog extraction.

Use separate Tasks for each marketplace so country, source, pricing, and failure semantics stay
clear in downstream monitoring.

### FAQ

**Can I mix countries in one run?**
Yes. Each URL selects its own storefront. Country-qualified product IDs can also be mixed.

**How are duplicate inputs handled?**
The Actor deduplicates by storefront, shop ID, and item ID before fetching or charging items.

**Will a failed product be charged as an item?**
No. The item event is emitted only after a validated product record is ready for delivery.

**Can I request more than 500 products?**
Split the input into bounded Tasks or batches. The per-run limit protects runtime, proxy cost,
and predictable retries.

**Are the image and video files downloaded?**
No. The Actor returns public media URLs and blocks media downloads during extraction.

**Can I schedule it?**
Yes. Save the input as an Apify Task and use a schedule. Keep historical datasets if you need
to compare product snapshots over time.

# Actor input Schema

## `startUrls` (type: `array`):

Public Shopee product URLs from Singapore, Malaysia, Indonesia, Thailand, Philippines, Vietnam, Brazil, or Mexico. Both -i.shopId.itemId and /product/shopId/itemId URL formats are accepted.

## `productIds` (type: `array`):

Optional IDs in shopId:itemId format, using the default country below, or country:shopId:itemId format such as id:196846900:11089699432.

## `countryCode` (type: `string`):

Shopee storefront used for productIds entries that do not begin with a country code. Product URLs always select their own storefront automatically.

## `maxItems` (type: `integer`):

Maximum number of unique product records to process in one run.

## `maxRetries` (type: `integer`):

Fresh country-matched residential sessions to try after a blocked, incomplete, or transient response.

## Actor input object example

```json
{
  "startUrls": [
    {
      "url": "https://shopee.sg/product-i.131198971.6646421738"
    }
  ],
  "countryCode": "SG",
  "maxItems": 20,
  "maxRetries": 2
}
```

# Actor output Schema

## `dataset` (type: `string`):

Default dataset containing one record per successfully extracted product.

# 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 = {
    "startUrls": [
        {
            "url": "https://shopee.sg/product-i.131198971.6646421738"
        }
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("automation-lab/shopee-product-details-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 = { "startUrls": [{ "url": "https://shopee.sg/product-i.131198971.6646421738" }] }

# Run the Actor and wait for it to finish
run = client.actor("automation-lab/shopee-product-details-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 '{
  "startUrls": [
    {
      "url": "https://shopee.sg/product-i.131198971.6646421738"
    }
  ]
}' |
apify call automation-lab/shopee-product-details-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,automation-lab/shopee-product-details-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/ZDtsbahfcgzl0Nim0/builds/6QKmsdBmnMuB7D758/openapi.json
