# Tokopedia Scraper (`khadinakbar/tokopedia-scraper`) Actor

Scrape Tokopedia product details, category listings and shop catalogs by URL: price, rating, reviews, stock, shop and image. No login needed.

- **URL**: https://apify.com/khadinakbar/tokopedia-scraper.md
- **Developed by:** [Khadin Akbar](https://apify.com/khadinakbar) (community)
- **Categories:** E-commerce, MCP servers, Automation
- **Features:** Limited permissions
- **Stats:** 9 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $5.00 / 1,000 product details

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

### What is Tokopedia Scraper?

Tokopedia Scraper extracts product data from Tokopedia category pages, shop catalogs and product-detail URLs into a structured dataset. Each row is one product with its name, product ID and URL, display price and numeric rupiah price, rating, review count, stock, category breadcrumbs, badges such as Mall, ad flag, image, shop name and shop location. Ecommerce analysts, Indonesian sellers, brand managers and AI agents use it to monitor prices, research categories and track competitor shops on Indonesia's major marketplace, with no login or cookies.

### Why teams use it

- **One URL field, three page types.** Paste category (`/p/...`), shop or product URLs; the Actor detects the page type for each one.
- **Numbers ready for analysis.** `priceInt` is a plain integer in rupiah next to the display string `price`.
- **Stock and trust signals.** `stock`, `badges` (for example `Mall`) and `isAd` sit on every listing row.
- **Seller context.** `shopName` and `shopLocation` show who sells each product and from which city.
- **Paginated catalogs.** `maxPagesPerList` walks deeper into a category or shop, and duplicate products across pages are merged.

### Best fit for this Actor

- **Designed for** Tokopedia category browsing pages, public shop catalogs and individual product pages.
- **Best fit for** price and stock monitoring, category share-of-shelf research and competitor shop tracking in Indonesia.
- Category and shop URLs are the browse path; keyword search pages sit outside this Actor's URL types.
- To compare the same category on another Southeast Asian marketplace, use [Shopee Scraper](https://apify.com/khadinakbar/shopee-scraper) alongside this Actor.
- When you also track Lazada sellers, continue with [Lazada Scraper](https://apify.com/khadinakbar/lazada-scraper) for that marketplace.

### Example workflow: smartphone price tracking

A pricing analyst at a phone distributor starts with the Tokopedia smartphone category URL `https://www.tokopedia.com/p/handphone-tablet/handphone` and two competitor shop URLs. She sets `maxPagesPerList` to 5 and `maxResults` to 400. The dataset returns each listing's `priceInt`, `stock`, `rating`, `reviewCount`, `badges` and `shopName`. She compares competitor prices on the same models, flags listings with low stock, then schedules the run daily and exports the rows to a spreadsheet that charts price movement per model.

### Input

```json
{
  "startUrls": [
    "https://www.tokopedia.com/p/handphone-tablet/handphone"
  ],
  "maxResults": 100,
  "maxPagesPerList": 5,
  "proxyConfiguration": { "useApifyProxy": true }
}
```

| Field | Type | What it controls |
|---|---|---|
| `startUrls` | array of strings | Required. Tokopedia category (`/p/...`), shop or product-detail URLs. |
| `maxResults` | integer | Products returned across all URLs. Default 100. |
| `maxPagesPerList` | integer | Pages followed per category or shop URL. Default 5. Product URLs are always one page. |
| `proxyConfiguration` | object | Apify Proxy settings. Default Apify Proxy; residential Indonesia suits large or concurrent jobs. |

| URL you paste | What each row represents |
|---|---|
| `https://www.tokopedia.com/p/handphone-tablet/handphone` | One product card from the category listing |
| `https://www.tokopedia.com/{shop}` or `.../{shop}/product` | One product from the shop catalog |
| `https://www.tokopedia.com/{shop}/{product-slug}` | One product-detail record |

### Output

One dataset row per product. The `type` field tells you which page type produced it.

| Field | What it contains |
|---|---|
| `type`, `productId` | Row type (such as `listing`) and Tokopedia product ID |
| `name`, `url` | Product title and product page URL |
| `price`, `priceInt` | Display price string and integer price in rupiah |
| `rating`, `reviewCount` | Rating and number of reviews |
| `stock` | Units in stock as listed |
| `categoryBreadcrumbs` | Category path such as `Handphone & Tablet/Handphone/Android OS` |
| `badges`, `isAd` | Store badges such as `Mall` and the sponsored-listing flag |
| `imageUrl` | Product image |
| `shopName`, `shopLocation` | Seller name and city |
| `sourceUrl`, `scrapedAt` | The URL you supplied and the collection time |

```json
{
  "type": "listing",
  "productId": "103313329805",
  "name": "Motorola Moto G86 Power 5G 8GB 256GB - Dimensity7400 - 6720mAh - 6.67\" pOLED 1.5K 120Hz Garansi Resmi Indonesia",
  "url": "https://www.tokopedia.com/agres-id-tangerang-selatan/motorola-moto-g86-power-5g-8gb-256gb-dimensity7400-6720mah-6-67-poled-1-5k-120hz-garansi-resmi-indonesia-produk-asli-1732578579216041285-1735327867464549701",
  "price": "Rp4.759.000",
  "priceInt": 4759000,
  "rating": 5,
  "reviewCount": 17,
  "stock": 11,
  "categoryBreadcrumbs": "Handphone & Tablet/Handphone/Android OS",
  "badges": ["Mall"],
  "imageUrl": "https://p16-images-sign-sg.tokopedia-static.net/tos-alisg-i-aphluv4xwc-sg/7b84cef85f4344a88e30e15512c1c835~tplv-aphluv4xwc-white-pad-v1:250:250.jpeg",
  "isAd": false,
  "shopName": "Agres ID Tangerang Selatan",
  "shopLocation": "Kota Tangerang Selatan",
  "sourceUrl": "https://www.tokopedia.com/p/handphone-tablet/handphone",
  "scrapedAt": "2026-10-01T01:43:57.790Z"
}
```

Product-detail URLs return the same core fields with the deeper product-page data Tokopedia publishes, such as price before discount, discount, rating breakdown and description.

### Pricing

This Actor uses Pay per event with Apify platform usage included in the event price. There are three events:

- **Actor Start**, once per run.
- **Listing product**, for each product saved from a category or shop catalog page.
- **Product detail**, for each product saved from a product-detail URL.

Worked example: one category URL with `maxResults` set to 100 costs one Actor Start event plus 100 Listing product events. Adding five product-detail URLs adds five Product detail events. Each product is charged once even when it appears on several pages. Check the live Pricing tab on this page for current event prices.

### API example

```bash
curl -X POST "https://api.apify.com/v2/acts/khadinakbar~tokopedia-scraper/run-sync-get-dataset-items?token=YOUR_API_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"startUrls": ["https://www.tokopedia.com/p/handphone-tablet/handphone"], "maxResults": 50, "maxPagesPerList": 2}'
```

```python
from apify_client import ApifyClient

client = ApifyClient("YOUR_API_TOKEN")
run = client.actor("khadinakbar/tokopedia-scraper").call(
    run_input={"startUrls": ["https://www.tokopedia.com/p/handphone-tablet/handphone"], "maxResults": 50}
)
for product in client.dataset(run["defaultDatasetId"]).iterate_items():
    print(product["name"][:60], product["priceInt"], product["stock"], product["shopName"])
```

### Use it with AI agents (MCP)

Connect the Actor to Claude, ChatGPT, Cursor or another MCP client through [Apify MCP](https://mcp.apify.com) and ask:

> Scrape the first 60 products from https://www.tokopedia.com/p/handphone-tablet/handphone and tell me the median price, the share of Mall-badged listings and the five shops with the most products.

The agent reads product rows with `get-dataset-items` and can cite `url` and `scrapedAt` as provenance. `maxResults` caps both the dataset and the cost, which keeps exploratory agent runs inexpensive.

### Best results

| Starting situation | Helpful action | Expected outcome |
|---|---|---|
| A topic you would normally search for | Open the matching Tokopedia category and paste its `/p/...` URL | A server-rendered category listing to paginate |
| A competitor seller | Paste the shop URL or its `/product` page | That shop's catalog |
| A deeper category pull | Raise `maxPagesPerList` together with `maxResults` | More pages per category |
| Large or parallel jobs | Choose Apify residential proxy in Indonesia | Steadier throughput |
| Daily price tracking | Schedule the same URLs and compare `priceInt` by `productId` | A clean price history per product |

### Builder's note

I built this around Tokopedia's own server-rendered category, shop and product pages, so each row reflects what a shopper sees without a browser session. I designed separate events for listing cards and product-detail pages because a detail page carries more data than a card. I found that analysts compare prices constantly, so every row includes the integer `priceInt` beside the formatted rupiah string.

### FAQ

#### Can I search Tokopedia by keyword?

The Actor reads category, shop and product URLs. For a keyword, open the closest Tokopedia category in your browser and paste that URL.

#### Do I need a login or an Indonesian IP?

No login or cookies. The default Apify Proxy works for normal runs, and an Indonesian residential proxy is a good choice for large jobs.

#### Are prices in rupiah?

Yes. `price` is the display string and `priceInt` is the integer value in rupiah.

### Responsible use

This Actor collects publicly available product and shop data from Tokopedia. Use it in line with Tokopedia's terms and applicable laws, including Indonesian data-protection law, and keep the data to legitimate purposes such as price monitoring and market research. Tokopedia is a trademark of its owner, and this independent Actor is not affiliated with or endorsed by Tokopedia. For questions, open a ticket in the Issues tab.

# Changelog

This Actor's version history is a separate document: https://apify.com/khadinakbar/tokopedia-scraper/changelog.md

# Actor input Schema

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

Tokopedia URLs to scrape; the mode is auto-detected per URL. Accepts product detail pages (e.g. 'https://www.tokopedia.com/{shop}/{product-slug}'), category pages ('https://www.tokopedia.com/p/handphone-tablet/handphone'), and shop catalog pages ('https://www.tokopedia.com/{shop}' or '.../{shop}/product'). Free-text search result URLs ('/search?q=...') are NOT supported because Tokopedia loads them from a blocked API — browse by category or shop instead.

## `maxResults` (type: `integer`):

Maximum number of products to return across all URLs combined. The actor stops (and stops charging) once this cap is reached. Defaults to 100. Set lower for cheap test runs; raise for large catalog pulls.

## `maxPagesPerList` (type: `integer`):

How many pages to paginate through for each category or shop URL (each page yields up to ~80 products). Defaults to 5. Ignored for product detail URLs, which are always a single page. Raise to go deeper into a category or shop catalog.

## `proxyConfiguration` (type: `object`):

Proxy used for requests. Defaults to Apify datacenter proxy, which works for normal usage thanks to Chrome-TLS impersonation. For maximum reliability on large or concurrent jobs, select Apify RESIDENTIAL (ideally Indonesia) or supply your own residential proxy URLs — residential exit IPs avoid Tokopedia's occasional edge resets entirely.

## Actor input object example

```json
{
  "startUrls": [
    "https://www.tokopedia.com/p/handphone-tablet/handphone",
    "https://www.tokopedia.com/cuan-gadgetid/product"
  ],
  "maxResults": 100,
  "maxPagesPerList": 5,
  "proxyConfiguration": {
    "useApifyProxy": true
  }
}
```

# Actor output Schema

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

All product records (listing and detail) scraped across the input URLs. Download as JSON, CSV, Excel, HTML, or RSS.

# 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": [
        "https://www.tokopedia.com/p/handphone-tablet/handphone"
    ],
    "maxResults": 100,
    "maxPagesPerList": 5,
    "proxyConfiguration": {
        "useApifyProxy": true
    }
};

// Run the Actor and wait for it to finish
const run = await client.actor("khadinakbar/tokopedia-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": ["https://www.tokopedia.com/p/handphone-tablet/handphone"],
    "maxResults": 100,
    "maxPagesPerList": 5,
    "proxyConfiguration": { "useApifyProxy": True },
}

# Run the Actor and wait for it to finish
run = client.actor("khadinakbar/tokopedia-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": [
    "https://www.tokopedia.com/p/handphone-tablet/handphone"
  ],
  "maxResults": 100,
  "maxPagesPerList": 5,
  "proxyConfiguration": {
    "useApifyProxy": true
  }
}' |
apify call khadinakbar/tokopedia-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,khadinakbar/tokopedia-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/dcoN7sCL3xgwvRhz4/builds/ky1ZYIILd7fHIJpyE/openapi.json
