# Shopee Scraper - Product Prices, Ratings & Discounts, 8 Markets (`s-r/shopee-scraper`) Actor

Shopee scraper for keyword searches, categories and product links in Indonesia, Singapore, Malaysia, Thailand, Vietnam, Philippines, Taiwan and Brazil. Per product: name, shop and item IDs, link, price, currency, discount, rating and seller location. Optional details add brand, category and images.

- **URL**: https://apify.com/s-r/shopee-scraper.md
- **Developed by:** [SR](https://apify.com/s-r) (community)
- **Categories:** E-commerce, Automation
- **Features:** Limited permissions
- **Stats:** 22 total users, 13 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $2.00 / 1,000 per-run start fees

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.

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

## What's an Apify Actor?

An Actor is a serverless cloud program that runs on the Apify platform. It has two run modes.
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.

Apify vocabulary and the platform model are defined once, in the agent quickstart at https://apify.com/agents.md.

## 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.

Do not guess an integration path. Every one of them is in the agent quickstart at https://apify.com/agents.md: the Apify MCP server, Agent Skills with the Apify CLI, the JavaScript and Python clients, the REST API, and the account-free path for an agent with no human to sign in. It also carries the rule on stating cost before the first paid run.

For examples already wired to this Actor's own input schema, see the [API](#api) section below.

Each client library has reference documentation the quickstart does not restate: [JavaScript/TypeScript](https://docs.apify.com/api/client/js/docs.md) (`npm install apify-client`) and [Python](https://docs.apify.com/api/client/python/docs.md) (`pip install apify-client`).

# README

## Shopee Scraper

Shopee Scraper collects products from keyword searches, category pages and individual product links across eight Shopee markets, for price monitoring, assortment research and marketplace analysis. Get one dataset row per product with its name, identifiers, link, price, currency, discount, rating and seller location when Shopee provides them. Optional details add product descriptions, images, brands and seller attributes.

You do not need a Shopee seller account, an API key or your own login. Enter search terms such as `headphone` or `sepatu`, paste category or product links, choose a market and download the result as JSON, CSV, Excel or through the Apify API. The actor is a practical way to scrape Shopee data when the official Shopee API only covers your own shop.

### Shopee Scraper input

Choose a market with `market`: Indonesia (`id`), Singapore (`sg`), Malaysia (`my`), Thailand (`th`), Vietnam (`vn`), Philippines (`ph`), Taiwan (`tw`) or Brazil (`br`). The default remains Indonesia. Use terms in the market's own language for useful results. All existing input names and defaults remain available, so saved tasks and API integrations can keep their current configuration.

Provide `searchTerms`, `categoryUrls`, `productUrls`, or a combination. Searches run first, followed by categories and individual products. Each list accepts strings. API input also accepts comma-separated or newline-separated text. Category URLs can be full Shopee links or paths such as `/Elektronik-cat.11044258`. Individual product URLs accept both seller-title links ending in `-i.shop.item` and canonical `/product/shop/item` links.

`pagesPerSearch` controls how many pages to read per term, from one to twenty. Its default is one. `maxProducts` caps the entire run at between one and 5000 unique products; the default is 100. Products appearing in multiple searches or categories are delivered once, with the first source retained. Reaching the cap ends collection. A deeper search does not guarantee a fixed number of additional products because Shopee can repeat results between pages.

`fetchDetails` defaults to false. Enable it when descriptions, product images, brands or category identifiers matter to your project. `concurrency` sets parallel detail requests, from one to eight, with a default of three. `attempts` remains available from one to fifteen, with a default of four. Larger detail requests take longer than collecting listing cards alone.

### Output and product fields

The default dataset contains one row for each delivered product. Existing fields retain their names and JSON types: `shop_id`, `item_id`, `product_url`, `title`, `price`, `price_original`, `currency`, `discount_percent`, `rating`, `location`, `list_position`, `market`, `source`, `source_input` and `position`.

Prices are numeric amounts in the row's stated currency. They are not converted into a different currency. Indonesian rupiah and Singapore dollars use different number separators on Shopee; the scraper normalises those separators while retaining the currency. A missing price is null, not zero. Original prices and discounts are populated only when the source publishes them.

With details enabled, rows may also include `description`, `image`, `brand`, `brand_id`, `cat_id`, `condition`, `ctime`, `shop_location`, `item_status`, `images` and `attributes`. Availability depends on the product page. Some pages expose a product preview with a name, description and image but omit brand or category data. Those limitations are reported in the run summary. `sold_count` and `stock` remain null in the anonymous detail route.

Additional fields help join the output with other product datasets: `product_id`, `url`, `country`, `country_code`, `fetched_at` and `image_url`. The original fields stay present. Use `fetched_at` to record when a row was collected and the uppercase country fields to identify its market. `source` continues to identify a search, category, individual URL or session API result.

#### Example Shopee Scraper output

A real row from a Singapore search for `headphone` (`market: "sg"`, `searchTerms: ["headphone"]`):

```json
{
  "shop_id": "1800354109",
  "item_id": "53609296010",
  "product_url": "https://shopee.sg/product/1800354109/53609296010",
  "list_position": 1,
  "market": "sg",
  "title": "Foldable Wireless Headphones Heavy Bass Bluetooth Gaming Headset Full Ear Gaming Card",
  "price": 9.0,
  "currency": "SGD",
  "discount_percent": 56,
  "rating": 4.7,
  "location": "SG",
  "price_original": null,
  "source": "search",
  "source_input": "headphone",
  "position": 1,
  "fetched_at": "2026-10-04T17:08:30.994238Z",
  "country_code": "SG",
  "country": "SG",
  "product_id": "53609296010",
  "url": "https://shopee.sg/product/1800354109/53609296010",
  "image_url": null
}
```

`price` is the current selling price in Singapore dollars, `discount_percent` is the discount Shopee shows on the card, and `price_original` is null because this card did not publish a struck-through price. `image_url` is filled when details are enabled.

### Use cases for Shopee data

- **Price monitoring.** Schedule the same searches or product links daily and compare `price`, `price_original` and `discount_percent` over time to follow price changes and promotions on Shopee.
- **Competitor and assortment research.** Collect every product a category page shows and see which shops, price bands and seller locations dominate a niche in a given market.
- **Market entry across Southeast Asia.** Run the same term in Indonesia, Malaysia, Thailand, Vietnam, the Philippines and Singapore to compare price levels and supply before launching a product.
- **Product research for resellers.** Combine ratings, discounts and seller locations to shortlist products that sell at a healthy price.
- **Catalogue enrichment.** Enable `fetchDetails` to add brands, category identifiers, descriptions and images to a list of product links you already track.

### Shopee Scraper compared with other options

The **Shopee API** (Shopee Open Platform) is meant for sellers and partners: it needs an approved app and authorisation from each shop, and it returns that shop's own orders and listings. It does not let you search the whole marketplace. Shopee Scraper works on the public catalogue, so you can look at any search term, category or product without a seller relationship.

Writing your own scraper is possible, but Shopee changes its pages often and each market uses its own domain, currency and number format. This actor handles the eight markets, normalises prices, removes duplicate products and keeps the output fields stable, so saved tasks and integrations continue to work.

Compared with single-purpose tools, one run can mix searches, category pages and product links under a single product cap, and you only pay for products that are actually delivered.

### Optional session cookies

Prices on ordinary listing pages do not require your own session cookies. If you supply `sessionCookies`, the actor first tries Shopee's session API for each search page. Use only cookies from your own Shopee account, supplied as name/value pairs or a cookie string. A successful session response can include additional price ranges, sold counts and stock information.

Expired or rejected cookies produce `session_refused`, followed by the ordinary listing route. The run can still deliver the publicly available catalogue and prices. Cookies are not included in result rows, error messages or continuation output. They are optional; leave this field empty when you do not need the session route.

### Shopee Scraper pricing

The existing pricing remains unchanged: $0.002 per run plus $0.001 per delivered product. The start fee applies once, including a run with no products. Product events apply only to rows actually delivered to the dataset. An empty result has no product charge. Set `maxProducts` to control the maximum product volume. Non-paying users have the existing ten-result run cap; rows beyond the cap are not charged.

### Errors and run summary

The default key-value store retains `summary` and, when needed, `errors`. The summary includes product counts, counts with titles, prices, ratings and brands, the selected market, detail and session settings, elapsed collection time and error count. Additional `partial` and `warnings` fields explain incomplete collection or limited detail coverage.

A page that cannot be read produces `blocked`; a failed detail page produces `detail_failed`. Listing products retain their existing name and price when optional details fail. A product-only link that yields no usable product information is not delivered as an empty paid result. Missing search terms and URLs produce `bad_input`. These ordinary source errors complete as successful runs, retaining any real products already collected.

### Frequently asked questions

#### Does every product have a price?

Most listing cards carry one, but Shopee can omit a price for a particular placement. The scraper retains the real product and returns null for unavailable amounts.

#### Why do some products have no brand or attributes?

Shopee does not expose the same detail coverage for every product. Enable `fetchDetails`, then check the summary warnings. Missing values are preserved as missing values rather than inferred from the title.

#### Can I combine searches and product links?

Yes. Searches, categories and product links share one run-wide product cap and deduplication rule. The first occurrence determines `source` and `source_input`.

#### What happens when a search has no useful matches?

Shopee sometimes returns popular recommendations even for an unusual term. The actor preserves the products that the source actually serves. It does not invent relevance scores or guarantee that every returned product matches the literal query.

#### Do I need a Shopee account or API key?

No. Searches, categories and product links work without an account. Session cookies are optional and only add fields that Shopee shows to signed-in users.

#### Which Shopee markets are supported?

Indonesia, Singapore, Malaysia, Thailand, Vietnam, the Philippines, Taiwan and Brazil. Each row carries `market`, `country_code` and the currency of that market.

# Actor input Schema

## `market` (type: `string`):

Which Shopee country site to read. The market is set by this, not by where the request comes from.

## `searchTerms` (type: `array`):

One per line, in the market's own language. Around forty products come back per term per page.

## `categoryUrls` (type: `array`):

Shopee category pages, such as /Elektronik-cat.11044258. A full link or a path both work.

## `productUrls` (type: `array`):

Individual products you already have. Combine with the above or use on their own.

## `pagesPerSearch` (type: `integer`):

How deep to walk each search.

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

Open each product page for the brand, category id, seller location, images and attributes. Off by default: the listing already carries the name, and this is one request per product.

## `maxProducts` (type: `integer`):

Stop after this many. Also the cost ceiling for the run.

## `concurrency` (type: `integer`):

How many product pages to open at once when details are on.

## `attempts` (type: `integer`):

How often to retry through a fresh exit before giving up on a page.

## `sessionCookies` (type: `object`):

Shopee withholds price, stock, rating and sold count from anyone who is not logged in. Paste your own cookies here as name/value pairs and the run uses Shopee's API instead, which carries all four. Without them you get the catalogue only.

## Actor input object example

```json
{
  "market": "id",
  "searchTerms": [
    "tas wanita",
    "headphone"
  ],
  "categoryUrls": [
    "https://shopee.co.id/Elektronik-cat.11044258"
  ],
  "productUrls": [
    "https://shopee.co.id/product/295064732/9112256351"
  ],
  "pagesPerSearch": 1,
  "fetchDetails": false,
  "maxProducts": 100,
  "concurrency": 3,
  "attempts": 4,
  "sessionCookies": {}
}
```

# Actor output Schema

## `products` (type: `string`):

One row per product.

## `summary` (type: `string`):

Products found per source, and how many carried a title and a brand.

## `errors` (type: `string`):

Pages that could not be read.

# 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 = {
    "market": "id",
    "searchTerms": [
        "sepatu"
    ],
    "categoryUrls": [],
    "productUrls": [],
    "sessionCookies": {}
};

// Run the Actor and wait for it to finish
const run = await client.actor("s-r/shopee-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 = {
    "market": "id",
    "searchTerms": ["sepatu"],
    "categoryUrls": [],
    "productUrls": [],
    "sessionCookies": {},
}

# Run the Actor and wait for it to finish
run = client.actor("s-r/shopee-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 '{
  "market": "id",
  "searchTerms": [
    "sepatu"
  ],
  "categoryUrls": [],
  "productUrls": [],
  "sessionCookies": {}
}' |
apify call s-r/shopee-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,s-r/shopee-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/z2tcW5Nk61IdiObI5/builds/vyyW4pEdEUy1EvUpC/openapi.json
