# LightInTheBox Scraper (`crawlerbros/lightinthebox-scraper`) Actor

Scrape LightInTheBox - a global marketplace with millions of products across electronics, watches, fashion, home & garden. Search by keyword, browse categories, fetch product detail pages with full specs, prices, ratings and reviews.

- **URL**: https://apify.com/crawlerbros/lightinthebox-scraper.md
- **Developed by:** [Crawler Bros](https://apify.com/crawlerbros) (community)
- **Categories:** E-commerce, Automation, Developer tools
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $3.00 / 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/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

## LightInTheBox Scraper

Scrape **LightInTheBox** (lightinthebox.com) — one of the world's largest cross-border online marketplaces with millions of products across electronics, watches, fashion, home & garden, wedding and party supplies. Search by keyword, browse any of 4,000+ categories, fetch full product detail pages with specifications and reviews, or feed your own URLs. HTTP-only against the site's server-rendered pages — **no auth, no cookies, no proxy required** (optional Apify proxy for heavy runs).

> **Transport note:** lightinthebox.com is protected by an Akamai edge that blocks plain HTTP clients (403 "Access Denied"). This actor therefore uses **browser-fingerprint impersonation** (curl\_cffi, TLS fingerprint of Chrome/Safari/Edge, rotated across retries), which is why it keeps working where plain `httpx`/`requests` clients get blocked.

### What this actor does

- **Four modes:** `search`, `byCategory`, `byProductIds`, `byUrls`
- **Full product data:** price, original price, discount %, rating, review count, availability, brand, images, specifications, selling points, customer reviews
- **20 market locales:** English, German, French, Spanish, Italian, Portuguese, Japanese, Russian, Dutch, Arabic, Norwegian, Danish, Swedish, Finnish, Hebrew, Polish, Czech, Greek, Romanian, Hungarian
- **Sorting:** relevance, popularity, price low-to-high, price high-to-low
- **Filters:** price range, minimum rating, minimum review count, title keyword
- **Automatic pagination** (60 products per page) up to a page cap
- **Empty fields are omitted** — every record is compact and null-free

### Output per product card (mode = search / byCategory)

- `productId` — numeric LightInTheBox product ID
- `title`, `brand`
- `productUrl` — canonical product page URL
- `price` — current price (USD)
- `originalPrice` — pre-discount price, when shown
- `discountPercent` — savings %, when original price is shown
- `currency` — `USD`
- `ratingValue` — average rating (0–5)
- `reviewCount` — number of ratings
- `imageUrl` — main product image (CDN, hotlink-free)
- `inStock` — availability
- `position` — rank on the results page
- `query` / `categoryId` — the search term or category that produced the record
- `sourceUrl` — the page the record came from
- `recordType: "productCard"`, `scrapedAt`

### Output per product detail (mode = byProductIds / byUrls, or `includeFullDetails`)

Everything from the card plus:

- `description` — when the page carries one
- `specifications` — key/value map (gender, type, material, size, etc.)
- `sellingPoints[]` — selling-point bullets
- `mpn`, `sku`, `color`, `size`
- `imageUrls[]` — all gallery images at full size
- `priceValidUntil`, `itemCondition`
- `reviews[]` — rating, date, body and author of featured reviews
- `categories[]` — category breadcrumb (name + URL)
- `recordType: "product"`, `scrapedAt`

### Output per failure

When a product or page cannot be fetched after retries, a typed record is emitted:

- `recordType: "error"`, `errorType` (`fetch_failed` / `not_found` / `parse_failed` / `invalid_url`), `message`, `sourceUrl`, `scrapedAt`

### Input

| Field | Type | Default | Description |
|---|---|---|---|
| `mode` | string | `search` | `search` / `byCategory` / `byProductIds` / `byUrls` |
| `searchQuery` | string | `watch` | Keyword to search for (mode=search) |
| `category` | string | – | Top-level category dropdown, e.g. `women-s-clothing_71` (mode=byCategory) |
| `categoryUrl` | string | – | Full URL of any category page, incl. sub-categories (mode=byCategory) |
| `productIds` | array | – | Numeric product IDs, e.g. `["10116681"]` (mode=byProductIds) |
| `startUrls` | array | – | Product / category / search URLs (mode=byUrls) |
| `language` | string | `en` | Market locale: `en` `de` `fr` `es` `it` `pt` `ja` `ru` `nl` `ar` `no` `da` `sv` `fi` `he` `pl` `cz` `gr` `ro` `hu` |
| `sortBy` | string | `relevance` | `relevance` / `popularity` / `priceLowToHigh` / `priceHighToLow` |
| `minPrice` | number | `0` | Keep products priced ≥ this value (USD) |
| `maxPrice` | number | `100000` | Keep products priced ≤ this value (USD) |
| `minRating` | number | `0` | Keep products rated ≥ this value (0–5) |
| `minReviewCount` | integer | `0` | Keep products with ≥ this many reviews |
| `containsKeyword` | string | – | Keep products whose title contains this text (case-insensitive) |
| `includeFullDetails` | boolean | `false` | Also fetch each product's detail page and emit full records |
| `maxItems` | integer | `50` | Max records to emit (1–10 000) |
| `maxPages` | integer | `20` | Max result pages per query (60 products/page) |
| `proxyConfiguration` | object | AUTO | Optional — works without proxy |

#### Example: keyword search

```json
{
  "mode": "search",
  "searchQuery": "led lights",
  "language": "en",
  "sortBy": "priceLowToHigh",
  "minPrice": 5,
  "maxItems": 100
}
```

#### Example: browse a category with details

```json
{
  "mode": "byCategory",
  "category": "watches_35798",
  "includeFullDetails": true,
  "minRating": 4.5,
  "maxItems": 20
}
```

#### Example: fetch specific products

```json
{
  "mode": "byProductIds",
  "productIds": ["10116681", "9767734", "9340231"],
  "language": "de"
}
```

#### Example: full catalog crawl from your own URLs

```json
{
  "mode": "byUrls",
  "startUrls": [
    {"url": "https://www.lightinthebox.com/en/c/quartz-watches_113738"},
    {"url": "https://www.lightinthebox.com/en/p/lige-men-quartz-watch_p10116681.html"},
    {"url": "https://www.lightinthebox.com/en/search?q=smart+watch"}
  ],
  "maxItems": 500
}
```

### Use cases

- **Price intelligence** — track LightInTheBox pricing, discounts and availability over time
- **Marketplace monitoring** — watch new arrivals and best sellers across categories
- **Product research** — enrich competitor/comparison databases with specs and ratings
- **Dropshipping research** — discover products, margins (price vs original price) and social proof (rating + review count) in one pass
- **Brand & category analytics** — aggregate rating distributions and review volumes per category
- **E-commerce migration** — pull a full product catalog for storefront prototyping

### FAQ

#### What is the data source?

This actor scrapes the public product listing and detail pages of **LightInTheBox** (lightinthebox.com), a global multi-category online marketplace. All data comes from the site's server-rendered HTML and its embedded structured data (schema.org Product markup).

#### Is this actor affiliated with LightInTheBox?

No. This is an independent third-party actor built on the public website.

#### Data source history — why was this actor created?

This actor **replaces the original "Bonanza (bonanza.com)" marketplace slot** on this marketplace:

1. **Bonanza → Fruugo:** the original Bonanza slot was first replaced by **Fruugo (fruugo.com)**, which is the same category (global multi-category marketplace).
2. **Fruugo → LightInTheBox:** Fruugo hard-blocks **all** Apify cloud egress — direct and AUTO proxy requests return HTTP 403 with a ~6 KB Cloudflare WAF block body across every market (including us/il), making it unusable from the Apify platform. It was therefore replaced by **LightInTheBox (lightinthebox.com)**, another global multi-category marketplace (electronics, watches, fashion, home & garden) that serves its pages to datacenter IPs without any bot challenge.

The old `FruugoScraper` folder was left untouched in the repository; this actor is a fresh, independent build.

#### Does it require a proxy, API key or cookies?

No. LightInTheBox serves full server-rendered HTML to plain HTTP clients. The actor works on the free plan with zero credentials. A proxy configuration is offered as an optional escalation if you scrape at very high volume and hit rate limits.

#### Are the image URLs accessible?

Yes. Product images are served from the `litb-cgis.rightinthebox.com` CDN and respond with `200 image/jpeg` to plain anonymous requests — no Referer, cookies or signed tokens needed.

#### How many products are available?

LightInTheBox lists hundreds of thousands of products across 4,000+ categories (per its public category sitemap) in 20 languages.

#### How does pagination work?

Search and category pages show 60 products per page. The actor follows `?page=2`, `?page=3`, … automatically until results run out or `maxPages` is reached.

#### Why are some fields missing on some records?

LightInTheBox only renders certain fields for certain products (e.g. no rating on brand-new items, no original price when there is no discount). Missing values are omitted rather than filled with placeholders — this keeps every record clean and reliable.

#### How fresh is the data?

Every record is scraped live at run time and carries a `scrapedAt` UTC timestamp. Nothing is cached between runs.

#### What about reviews?

Full review lists are loaded by the site's front-end JavaScript; the server-rendered page embeds a few featured reviews per product, which the actor captures. Review counts come from the product's structured data.

#### Limitations

- Full review *lists* are client-side only; only the featured reviews embedded in the page markup are captured.
- Category pages and search pages are limited to 60 products per page; the actor respects the same pagination the website exposes.
- The site's filtering (price, brand, etc.) is applied client-side; the actor therefore filters results locally, which limits filtering to the pages it actually crawled.

# Actor input Schema

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

What to scrape: keyword search, category browse, product detail pages by ID, or raw URLs.

## `searchQuery` (type: `string`):

Keyword to search for (mode=search). Example: `watch`, `led lights`, `phone case`. Paginates automatically.

## `category` (type: `string`):

Top-level category to browse (mode=byCategory). URLs look like /en/c/<slug>\_<id>. Sub-categories: use `categoryUrl` with the full URL from lightinthebox.com.

## `categoryUrl` (type: `string`):

Full URL of any LightInTheBox category page, e.g. https://www.lightinthebox.com/en/c/quartz-watches\_113738 (mode=byCategory). Takes precedence over `category` when both are set.

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

Numeric LightInTheBox product IDs (the number in \_p<ID>.html URLs) to fetch full detail pages for (mode=byProductIds).

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

Product, category or search page URLs on lightinthebox.com (mode=byUrls). Each URL is classified automatically and scraped accordingly.

## `language` (type: `string`):

Marketplace locale — controls the site sub-directory (e.g. /en/, /de/, /fr/). Prices are shown in USD by LightInTheBox across markets.

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

Sort order for search and category results (modes=search/byCategory).

## `minPrice` (type: `number`):

Only keep products whose price is >= this value (USD). Applied after scraping.

## `maxPrice` (type: `number`):

Only keep products whose price is <= this value (USD). Applied after scraping.

## `minRating` (type: `number`):

Only keep products with an average rating >= this value (0-5). Products without a rating always pass through.

## `minReviewCount` (type: `integer`):

Only keep products with at least this many reviews.

## `containsKeyword` (type: `string`):

Only keep products whose title contains this substring (case-insensitive).

## `includeFullDetails` (type: `boolean`):

For search/category modes: additionally visit each product's detail page and emit a full-detail record (description, specifications, selling points, all images, reviews). Doubles request volume.

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

Maximum number of records to emit.

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

Maximum result pages to crawl per search query or category (60 products per page).

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

Optional. LightInTheBox works without a proxy. If you hit rate limits, enable Apify proxy (datacenter/automatic).

## Actor input object example

```json
{
  "mode": "search",
  "searchQuery": "watch",
  "productIds": [
    "10116681",
    "9767734"
  ],
  "language": "en",
  "sortBy": "relevance",
  "minPrice": 0,
  "maxPrice": 100000,
  "minRating": 0,
  "minReviewCount": 0,
  "includeFullDetails": false,
  "maxItems": 5,
  "maxPages": 2,
  "proxyConfiguration": {
    "useApifyProxy": true
  }
}
```

# Actor output Schema

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

Dataset containing all scraped LightInTheBox products (product cards and full product details).

# 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",
    "searchQuery": "watch",
    "productIds": [
        "10116681",
        "9767734"
    ],
    "language": "en",
    "sortBy": "relevance",
    "includeFullDetails": false,
    "maxItems": 5,
    "maxPages": 2,
    "proxyConfiguration": {
        "useApifyProxy": true
    }
};

// Run the Actor and wait for it to finish
const run = await client.actor("crawlerbros/lightinthebox-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",
    "searchQuery": "watch",
    "productIds": [
        "10116681",
        "9767734",
    ],
    "language": "en",
    "sortBy": "relevance",
    "includeFullDetails": False,
    "maxItems": 5,
    "maxPages": 2,
    "proxyConfiguration": { "useApifyProxy": True },
}

# Run the Actor and wait for it to finish
run = client.actor("crawlerbros/lightinthebox-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",
  "searchQuery": "watch",
  "productIds": [
    "10116681",
    "9767734"
  ],
  "language": "en",
  "sortBy": "relevance",
  "includeFullDetails": false,
  "maxItems": 5,
  "maxPages": 2,
  "proxyConfiguration": {
    "useApifyProxy": true
  }
}' |
apify call crawlerbros/lightinthebox-scraper --silent --output-dataset

```

## MCP server setup

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