# WatchCharts Scraper — Market Price & Reference (`crawloop/watchcharts-scraper`) Actor

Scrape WatchCharts market and retail prices by reference or brand. One row is one watch, with collection, volatility rank, and risk score. No login.

- **URL**: https://apify.com/crawloop/watchcharts-scraper.md
- **Developed by:** [Andrej Kiva](https://apify.com/crawloop) (community)
- **Categories:** E-commerce, Automation, Lead generation
- **Stats:** 2 total users, 1 monthly users, 50.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $5.00 / 1,000 watch prices

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

## WatchCharts Scraper — Market Price & Reference

> **Disclaimer:** Unofficial tool — not affiliated with, sponsored by, or endorsed by WatchCharts or its affiliates. Data is read from publicly accessible brand, search, and model overview pages only. No login. You are responsible for complying with applicable law (including GDPR where personal data appears) and the site’s terms. No warranty on accuracy or availability. Provided for informational and research use.

**WatchCharts scraper** for public market prices. One row is one watch: reference, retail price, pre-owned market price, and the ranks printed on the model page (volatility, risk, sales volume). Search by reference, read a brand index, or open a model URL. Use it as a **WatchCharts API alternative** from **Python**, **Node.js**, **cURL**, or **Apify MCP**, and export the dataset as JSON.

**Best for:** dealers and pricing apps that need a current market price next to a reference number.

### Suite

| Chrono24 Scraper | WatchCharts Scraper |
| :--- | :--- |
| [Chrono24 Scraper](https://apify.com/crawloop/chrono24-scraper) — live dealer listings | WatchCharts Scraper ◄── you are here — market price and reference |

### When to use this Actor

- **A reference search** — Put `126610LN` in Search queries. The result list has no price, so the Actor opens each model page up to Maximum watches and saves the market price on that same row.
- **A brand index** — Set Brands to `Rolex` or `Patek Philippe` for the first page of model cards.
- **A model overview** — Paste a public model page URL. The row includes collection, dial color, and the percentile ranks.
- **Richer cards** — Turn on Open model pages to add those ranks onto each listing card. That opens one extra page per watch and is still one saved row.

### When not to use this Actor

- **Live dealer asks and shipping** — Use the Chrono24 Scraper for listing cards. This Actor reads the public price index, not a marketplace checkout.
- **Full price history, forecasts, or appraisals** — Those sit behind a member login. This Actor saves the prices and ranks shown on the public page.
- **A login session or private collection** — No account, no collection export.

### Key features

- **Market and retail price** — Number, currency, the printed text, and the as-of date when the page shows one.
- **Reference and collection** — Brand, model name, reference, and the related references on a model page.
- **Ranks** — Market price, one-year performance, volatility, risk, sales volume, days on market, and tenure, as printed.
- **One charge per watch** — A listing card and its optional model page are the same dataset row.

### Input

| Field | Required | Default | What it does |
| :--- | :--- | :--- | :--- |
| Search queries | No | — | Reference or model text. One public search page each |
| Brands | No | — | Brand index, such as Rolex |
| Page URLs | No | — | Brand, search, or model page |
| Maximum watches | No | 25 | Stop after this many rows (cap 200) |
| Maximum pages | No | 1 | Listing pages per search or brand (cap 5) |
| Open model pages | No | off | Add collection and ranks onto each card |
| Proxy | No | Residential, Germany | On by default. The public pages answer a normal browser. A datacenter IP is challenged before any card loads |

```json
{
  "searchQueries": ["126610LN"],
  "maxItems": 25,
  "maxPages": 1,
  "includeDetails": false
}
```

### Output

| Field | Meaning |
| :--- | :--- |
| `brand`, `modelName`, `reference` | Name on the card or model page |
| `collection`, `references`, `style`, `dialColor` | Specs from a model page |
| `marketPrice`, `marketPriceText`, `currency`, `marketPriceAsOf` | Pre-owned estimate |
| `retailPrice`, `retailPriceText`, `retailPriceAsOf` | Authorized-dealer price when printed |
| `marketRank`, `volatilityRank`, `riskScore` | Percentiles as printed |
| `oneYearPerformance`, `salesVolumeRank`, `daysOnMarket`, `marketTenure` | More percentiles from the model page |
| `status`, `caseMaterial`, `caseSize`, `waterResistance` | Badges on a listing card |
| `imageUrl`, `url` | Image and the public model URL |
| `sourceUrl`, `scrapedAt` | Page that was read, and the run time in UTC |

```json
{
  "recordType": "listing",
  "query": "126610LN",
  "brand": "Rolex",
  "modelName": "Submariner Date",
  "reference": "126610LN",
  "marketPrice": 14250,
  "marketPriceText": "€14,250",
  "currency": "EUR",
  "retailPrice": 9100,
  "retailPriceText": "€9,100",
  "status": "In Production",
  "caseMaterial": "Steel",
  "url": "https://watchcharts.com/watch_model/example/overview",
  "sourceUrl": "https://watchcharts.com/watches/search?q=126610LN",
  "scrapedAt": "2026-10-19T12:00:00Z"
}
```

### Use cases

- Price a reference before listing it, and keep the market price next to retail.
- Read the first page of a brand index when you want every in-production card, not one URL.
- Open a model page when you need the volatility rank and risk score, not only the price.
- Hand the reference to the Chrono24 Scraper when you also want live dealer listings.

### Integration examples

Replace `APIFY_TOKEN`. The slug below is the Store name.

#### Node.js

```javascript
import { ApifyClient } from "apify-client";

const client = new ApifyClient({ token: process.env.APIFY_TOKEN });
const run = await client.actor("crawloop/watchcharts-scraper").call({
  searchQueries: ["126610LN"],
  maxItems: 25,
  maxPages: 1,
});
const { items } = await client.dataset(run.defaultDatasetId).listItems();
console.log(items);
```

#### Python

```python
import os
from apify_client import ApifyClient

client = ApifyClient(os.environ["APIFY_TOKEN"])
run = client.actor("crawloop/watchcharts-scraper").call(run_input={
    "searchQueries": ["126610LN"],
    "maxItems": 25,
})
items = client.dataset(run["defaultDatasetId"]).list_items().items
print(len(items))
```

#### cURL

```bash
curl -X POST "https://api.apify.com/v2/acts/crawloop~watchcharts-scraper/runs?token=$APIFY_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"searchQueries":["126610LN"],"maxItems":25,"maxPages":1}'
```

### MCP and AI assistants

Use this Actor from AI tools via [Apify MCP](https://docs.apify.com/platform/integrations/mcp).
Connect your Apify account, then call this Actor by its Store name `crawloop/watchcharts-scraper`.

Example prompts:

- "Run WatchCharts Scraper for reference 126610LN and return brand, reference, market price, and retail price as JSON"
- "Scrape the Rolex brand page with WatchCharts Scraper, maximum 25 watches, and list references under the market price"
- "Run WatchCharts Scraper for 16610, then Chrono24 Scraper for the same reference and compare the market price with live listings"

### Suite next step

After the market price, pull live dealer listings with the [Chrono24 Scraper](https://apify.com/crawloop/chrono24-scraper).

### FAQ

**What is one row?**
One watch. A search or brand card is one row. Opening the model page adds fields to that same row. It is not a second charge, and it is not one row per history point.

**Does the price include the full chart history?**
No. The row keeps the current market price, the retail price, and the ranks printed on the public page. Multi-year history stays on the site for logged-in members.

**Which currency is the price in?**
The currency printed on the page. `currency` is EUR, USD, or GBP when the symbol is one of those. `marketPrice` is the number without the symbol.

**Do I need a login or a proxy?**
No login. Residential proxy is on by default because a datacenter address is challenged before the watch cards load. Turn Proxy off only for a local test.

**How do I export the rows?**
The run writes one watch per dataset row. Download JSON, CSV, or Excel from that dataset, or read it with the Node.js, Python, and cURL examples.

# Actor input Schema

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

Reference numbers or model names, such as 126610LN or Submariner. Each query is one public search page.

## `brands` (type: `array`):

Brand names for the public brand index, such as Rolex or Patek Philippe. One page of cards per brand unless Maximum pages is higher.

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

Public brand, search, or watch model pages. A model URL returns the overview (market price, ranks, and specs). A brand or search URL returns listing cards.

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

Stop after this many saved watches. The run also stops at 200.

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

Listing pages to read per search or brand. Page 1 is the HTML page. Later pages use the same session. Model URLs ignore this.

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

After a listing card, open its model page and add collection, ranks, and specs to the same row. Slower. Still one charge per saved watch.

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

Leave Apify Proxy off. Turn it on only if a run is blocked before any watch cards load.

## Actor input object example

```json
{
  "searchQueries": [
    "126610LN"
  ],
  "startUrls": [],
  "maxItems": 25,
  "maxPages": 1,
  "includeDetails": false,
  "proxyConfiguration": {
    "useApifyProxy": true,
    "apifyProxyGroups": [
      "RESIDENTIAL"
    ],
    "apifyProxyCountry": "DE"
  }
}
```

# Actor output Schema

## `results` (type: `string`):

Default dataset items — one watch per item.

# 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 = {
    "searchQueries": [
        "126610LN"
    ],
    "startUrls": [],
    "maxItems": 25,
    "maxPages": 1,
    "includeDetails": false
};

// Run the Actor and wait for it to finish
const run = await client.actor("crawloop/watchcharts-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 = {
    "searchQueries": ["126610LN"],
    "startUrls": [],
    "maxItems": 25,
    "maxPages": 1,
    "includeDetails": False,
}

# Run the Actor and wait for it to finish
run = client.actor("crawloop/watchcharts-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 '{
  "searchQueries": [
    "126610LN"
  ],
  "startUrls": [],
  "maxItems": 25,
  "maxPages": 1,
  "includeDetails": false
}' |
apify call crawloop/watchcharts-scraper --silent --output-dataset

```

## MCP server setup

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