# Tokopedia Search, Category & Price Drop Scraper (`dataspryva/tokopedia-search-category-and-price-drop-scraper`) Actor

Search Tokopedia by keyword, browse a category or top-sellers list, or look up specific product URLs, and get price, discount, rating, and seller details for each Indonesian marketplace listing.

- **URL**: https://apify.com/dataspryva/tokopedia-search-category-and-price-drop-scraper.md
- **Developed by:** [Dataspryva](https://apify.com/dataspryva) (community)
- **Categories:** E-commerce, Automation, Lead generation
- **Stats:** 2 total users, 1 monthly users, 87.5% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $0.49 / 1,000 results

This Actor is paid per event and usage. You are charged both the fixed price for specific events and for Apify platform usage.
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?

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

## Tokopedia Search, Category & Price Drop Scraper

Tokopedia is Indonesia's largest marketplace, and this actor turns its public product pages into a clean dataset. Search by keyword or search URL, browse a category, or paste product URLs to collect prices in Rupiah, discounts, ratings, sold counts, seller details, condition, stock, variants, and images. No account, login, or proxy setup is needed.

### What this actor does

- **Search products** by keyword or a Tokopedia search/find URL, with Tokopedia's real filters and five real sort orders.
- **Browse categories** from a `/p/...` URL or a numeric category ID.
- **Fetch product details** from Tokopedia product URLs: condition, stock, weight, minimum order, variants and child SKUs, description, rating breakdown, and campaign dates.
- **Price-drop view:** every record exposes the current price, original price, discount percentage, discount amount, and a `priceDropped` flag. Tokopedia does not publish historical prices, so this is a current-snapshot view rather than a price history.
- **Overview or detail:** keep search results fast, or enable `includeDetails` to enrich each row with the full product page.
- Empty fields are omitted from each record instead of being returned as null or blank.

### Output per product

| Field | Description |
|---|---|
| `productId` | Tokopedia product ID |
| `name` | Product name |
| `productUrl` | Direct product page URL |
| `price`, `priceText` | Current price in IDR, numeric and as displayed |
| `originalPrice`, `originalPriceText` | Pre-discount price when shown |
| `discountPercent`, `discountAmount` | Current discount |
| `priceDropped` | True when the original price is above the current price |
| `currency` | Always `IDR` |
| `rating`, `reviewCount` | Rating and, in detail mode, review count |
| `sold`, `soldText` | Units sold, parsed into a number plus the source label |
| `shop`, `shopId`, `shopUrl`, `shopLocation` | Seller identity and location |
| `shopTier` | `mall`, `power_shop`, or `regular` when known |
| `imageUrl`, `imageUrlOriginal` | Main image plus the signed source URL. Most normalized links are durable; a minority stay on a signed host and expire. |
| `categoryId`, `categoryName`, `categoryPath` | Category identity and breadcrumb path |
| `labels` | Promotional and service labels shown on the card |
| `badge` | Official/Power/Mall badge when one is visible |
| `preorder` | Whether the listing is a preorder |
| `condition`, `conditionText` | NEW/USED and its local display text (detail) |
| `status` | Product status such as ACTIVE (detail) |
| `stock`, `minOrder`, `maxOrder` | Availability and order limits (detail) |
| `weight`, `weightUnit` | Shipping weight (detail) |
| `isVariant`, `variants`, `variantChildren` | Variation axes and child SKUs with their prices and stock (detail) |
| `description` | Seller description (detail) |
| `specifications` | Best-effort key/value specifications parsed from the description (detail) |
| `ratingBreakdown` | Per-star rating counts and percentages (detail) |
| `imageUrls` | Full gallery of image URLs (detail; mostly durable) |
| `categoryBreadcrumb` | Category path with names and URLs (detail) |
| `campaignType`, `campaignEndsAt`, `campaignDiscountPercent`, `campaignStockSoldPercent` | Active campaign details when present (detail) |
| `mode`, `searchQuery`, `position`, `scrapedAt` | Provenance: mode, query, result position, and scrape time |

### Input

| Field | Type | Default | Description |
|---|---|---|---|
| `mode` | string | – | `search`, `categoryBrowse`, or `productDetails` |
| `searchQueries` | array | `[]` (prefill `["smartphone"]`) | Keywords to search (mode=search) |
| `searchUrls` | array | `[]` | Tokopedia search or `/find/` URLs (mode=search) |
| `categoryUrls` | array | `[]` | Tokopedia category URLs (mode=categoryBrowse) |
| `categoryIds` | array | `[]` | Numeric category IDs (mode=categoryBrowse) |
| `productUrls` | array | `[]` | Product page URLs (mode=productDetails) |
| `sortBy` | string | `relevance` | `relevance`, `newest`, `price_low`, `price_high`, `most_reviewed` |
| `priceMin`, `priceMax` | integer | – | Price range in IDR |
| `condition` | string | `any` | `any`, `new`, `used` |
| `shopType` | string | `any` | `any`, `mall`, `power_shop` |
| `minRating` | string | `any` | `any` or `4` |
| `city` | string | `any` | Common seller locations, or `any` |
| `cityId` | string | – | Exact Tokopedia city ID(s), comma-separated |
| `latestProductDays` | string | `any` | `any`, `7`, `14`, `30`, `90` |
| `discountOnly` | boolean | `false` | Only discounted products |
| `codOnly` | boolean | `false` | Only cash-on-delivery products |
| `freeShippingOnly` | boolean | `false` | Only products with the free-shipping offer |
| `preorder` | string | `any` | `any`, `ready_stock`, `preorder` |
| `includeDetails` | boolean | `false` | Enrich search/category rows from each product page |
| `maxItems` | integer | `100` | Maximum products, 1–6000 |

#### Example: search with filters

```json
{
  "mode": "search",
  "searchQueries": ["sepatu lari"],
  "sortBy": "price_low",
  "priceMin": 100000,
  "priceMax": 500000,
  "shopType": "mall",
  "minRating": "4",
  "maxItems": 50
}
```

#### Example: browse a category

```json
{
  "mode": "categoryBrowse",
  "categoryUrls": ["https://www.tokopedia.com/p/handphone-tablet/handphone"],
  "sortBy": "newest",
  "maxItems": 100
}
```

#### Example: full product details

```json
{
  "mode": "productDetails",
  "productUrls": [
    "https://www.tokopedia.com/pxofficialindonesia/kabel-data-usb-type-c-ultra-fast-charging-pd240w-charger-nylon-braided-laptop-tablet-smartphone-samsung-oppo-huawei-vivo-px-fcc-2m-1736805261334316721"
  ]
}
```

### Use cases

- **Price and discount monitoring** — compare current prices, discounts, and campaign end dates across a category or keyword.
- **Seller intelligence** — compare shop type, location, sold counts, and ratings across merchants.
- **Assortment planning** — browse a category to see the current product mix and pricing ladder.
- **Product research** — collect variants, child SKUs, stock, weight, condition, and descriptions for a shortlist.
- **Marketplace analytics** — feed clean product records into dashboards, spreadsheets, or a database.

### FAQ

**Do I need a Tokopedia account or login?**
No. The actor reads public product, search, and category pages.

**What currency are prices in?**
Indonesian Rupiah (IDR), returned as integers.

**What does "price drop" mean here?**
It means the product currently has a lower price than its displayed original price. Tokopedia does not publish a historical price series, so the actor cannot show a true past price. Run it on a schedule and compare `price` values to build your own history.

**Why are some fields missing?**
Tokopedia does not show every field on every listing. A product without a discount has no `originalPrice`; a listing without a description spec block has no `specifications`. The actor omits missing fields instead of guessing.

**Why do some product URLs fail?**
The actor needs the normal Tokopedia product URL (`/{shop}/{product-slug}-{id}`). Numeric product IDs alone do not resolve through the public site.

**How many products can I get per search?**
Up to 6,000 products per search slice. Tokopedia caps pagination at that point. For larger sets, split the work by keyword, category, price range, or location.

**Can I filter by seller city?**
Yes. Use the location dropdown for common cities, or `cityId` for an exact Tokopedia city ID from a Tokopedia search URL.

**Are image links permanent?**
The actor returns a normalized image URL and keeps the original signed URL in `imageUrlOriginal`. Most normalized links are durable, but a minority remain on Tokopedia's signed host; those expire within hours. Use `imageUrlOriginal` promptly or re-run the actor to refresh them.

**Is this affiliated with Tokopedia?**
No. This is an independent third-party actor that reads publicly available Tokopedia pages and is not operated by or affiliated with Tokopedia.

# Actor input Schema

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

What to scrape.

## `searchQueries` (type: `array`):

Keywords to search (mode=search). Example: smartphone, sepatu lari, kopi arabika.

## `searchUrls` (type: `array`):

Tokopedia search or /find/ URLs. Filters and sort already in the URL are applied.

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

Tokopedia category URLs such as https://www.tokopedia.com/p/handphone-tablet/handphone.

## `categoryIds` (type: `array`):

Numeric Tokopedia category IDs, for example 24 for Handphone.

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

Tokopedia product page URLs. Numeric IDs alone are not supported.

## `sortBy` (type: `string`):

Result order.

## `priceMin` (type: `integer`):

Minimum price in Indonesian Rupiah.

## `priceMax` (type: `integer`):

Maximum price in Indonesian Rupiah.

## `condition` (type: `string`):

Filter by product condition.

## `shopType` (type: `string`):

Filter by Tokopedia shop type.

## `minRating` (type: `string`):

Only show products rated 4 or higher.

## `city` (type: `string`):

Filter by a common seller location. Leave Any for all of Indonesia.

## `cityId` (type: `string`):

Exact Tokopedia city ID(s), comma-separated. Overrides the location dropdown.

## `latestProductDays` (type: `string`):

Only show products added recently.

## `discountOnly` (type: `boolean`):

Only show products currently on discount.

## `codOnly` (type: `boolean`):

Only show products that offer cash on delivery.

## `freeShippingOnly` (type: `boolean`):

Only show products with the free-shipping offer.

## `preorder` (type: `string`):

Filter by ready stock or preorder.

## `includeDetails` (type: `boolean`):

Add condition, stock, variants, description, and rating breakdown to search and category results. Slower and makes one extra request per product.

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

Maximum number of products to return.

## Actor input object example

```json
{
  "mode": "search",
  "searchQueries": [
    "smartphone"
  ],
  "searchUrls": [],
  "categoryUrls": [],
  "categoryIds": [],
  "productUrls": [],
  "sortBy": "relevance",
  "condition": "any",
  "shopType": "any",
  "minRating": "any",
  "city": "any",
  "latestProductDays": "any",
  "discountOnly": false,
  "codOnly": false,
  "freeShippingOnly": false,
  "preorder": "any",
  "includeDetails": false,
  "maxItems": 3
}
```

# Actor output Schema

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

Dataset containing all scraped Tokopedia products.

# 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 = {
    "mode": "search",
    "searchQueries": [
        "smartphone"
    ],
    "sortBy": "relevance",
    "condition": "any",
    "shopType": "any",
    "minRating": "any",
    "city": "any",
    "latestProductDays": "any",
    "discountOnly": false,
    "codOnly": false,
    "freeShippingOnly": false,
    "preorder": "any",
    "includeDetails": false,
    "maxItems": 3
};

// Run the Actor and wait for it to finish
const run = await client.actor("dataspryva/tokopedia-search-category-and-price-drop-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 = {
    "mode": "search",
    "searchQueries": ["smartphone"],
    "sortBy": "relevance",
    "condition": "any",
    "shopType": "any",
    "minRating": "any",
    "city": "any",
    "latestProductDays": "any",
    "discountOnly": False,
    "codOnly": False,
    "freeShippingOnly": False,
    "preorder": "any",
    "includeDetails": False,
    "maxItems": 3,
}

# Run the Actor and wait for it to finish
run = client.actor("dataspryva/tokopedia-search-category-and-price-drop-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 '{
  "mode": "search",
  "searchQueries": [
    "smartphone"
  ],
  "sortBy": "relevance",
  "condition": "any",
  "shopType": "any",
  "minRating": "any",
  "city": "any",
  "latestProductDays": "any",
  "discountOnly": false,
  "codOnly": false,
  "freeShippingOnly": false,
  "preorder": "any",
  "includeDetails": false,
  "maxItems": 3
}' |
apify call dataspryva/tokopedia-search-category-and-price-drop-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,dataspryva/tokopedia-search-category-and-price-drop-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/bOmVHQGZm6vdyV601/builds/0xhqWRRyaZ3YnEnaW/openapi.json
