# Chrono24 Watch Listing Scraper (`malek_oweis/chrono24-watch-listing-scraper`) Actor

Scrape luxury-watch listings from Chrono24 by brand, model or URL. One row per watch: brand, model, reference number, year, price, condition, movement, case size, box & papers status, seller country and images. Gets past Chrono24's Cloudflare block; no login.

- **URL**: https://apify.com/malek\_oweis/chrono24-watch-listing-scraper.md
- **Developed by:** [Malek Oweis](https://apify.com/malek_oweis) (community)
- **Categories:**
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $1.33 / 1,000 results

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

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

## Chrono24 Watch Listing Scraper

**Chrono24 blocks scrapers** — it sits behind Cloudflare plus a bot-risk engine, so a normal request gets a 403. That is why most Chrono24 Actors are slow, tiny, or broken.

This one gets through. Every request uses a **real browser TLS fingerprint** and runs through Apify's residential proxy, retrying on a fresh IP whenever it is challenged. The watch data is read straight out of each page's own JSON-LD — **no private API, no login, no captcha setup from you.**

Point it at a brand, a model, a reference, a search, or a single listing and get **one clean row per watch for sale**.

### What you get per watch

| Field | Meaning |
|---|---|
| `title`, `brand`, `model` | Watch identity |
| `referenceNumber` | Manufacturer reference / model number |
| `year` | Year of production (when the seller states it) |
| `price`, `currency` | Asking price and currency |
| `condition` | `New` · `Used` · `Refurbished` … |
| `availability`, `inStock` | Listing status |
| `movement` | `Automatic` · `Manual winding` · `Quartz` … |
| `caseMaterial`, `caseDiameterMm` | Case material and diameter in mm |
| `crystal`, `strapMaterial` | Crystal and strap/bracelet material |
| `jewels`, `powerReserveHours` | Caliber details, when Chrono24 exposes them |
| `gender` | `mens` · `womens` · `unisex` |
| `sellerCountry` | ISO country code of the seller |
| `hasBox`, `hasPapers`, `boxAndPapers` | Parsed from the listing text — the single biggest price driver on the used market |
| `imageUrl`, `imageCount` | First image and how many photos the listing has |
| `description` | The seller's full spec/description text |
| `listingId`, `url` | Chrono24 listing id and direct link |

### Input

```json
{
  "brands": ["rolex", "omega"],
  "urls": ["https://www.chrono24.com/rolex/submariner--mod1240.htm"],
  "maxListingsPerInput": 120,
  "scrapeDetails": true
}
```

- `brands` — brand names (`rolex`, `patek-philippe`, `audemars-piguet`, `a-lange-sohne` …). Each becomes a Chrono24 brand page and is paginated.
- `urls` — any `chrono24.com` page that lists watches: a **brand page**, a **model page** (`…--mod….htm`), a **reference page**, a **filtered search** (paste the URL with the filters applied on the site), or a single **listing** (`…--id….htm`).
- `maxListingsPerInput` — stop after this many watches per brand/URL (60 per page). `0` = no limit, hard-capped at 3000.
- `scrapeDetails` — `true` (default): open every listing for the full record. `false`: faster and cheaper, but only `title`, `price`, `currency`, `imageUrl` and `inStock` from the results page.
- `proxyConfiguration` — defaults to **Apify Residential**, which is required. Datacenter IPs get blocked by Cloudflare.

### Output

One dataset row per watch, plus a `SEARCH_SUMMARY` key-value record per brand/URL with
`listingsScraped`, `priceMin` / `priceAvg` / `priceMax`, `conditionBreakdown`,
`boxAndPapersCount`, `topSellerCountries` and `brandsSeen`.

#### Example row

```json
{
  "source": "rolex",
  "listingId": "47038909",
  "url": "https://www.chrono24.com/rolex/submariner-date--id47038909.htm",
  "title": "Rolex Submariner Date",
  "brand": "Rolex",
  "model": "Submariner Date",
  "referenceNumber": "116610LN",
  "year": "2018",
  "price": 12750,
  "currency": "USD",
  "condition": "Used",
  "availability": "InStock",
  "inStock": true,
  "movement": "Automatic",
  "caseMaterial": "Steel",
  "caseDiameterMm": 40,
  "crystal": "Sapphire crystal",
  "strapMaterial": "Steel",
  "jewels": 31,
  "powerReserveHours": 48,
  "gender": "unisex",
  "sellerCountry": "DE",
  "hasBox": true,
  "hasPapers": true,
  "boxAndPapers": true,
  "imageUrl": "https://img.chrono24.com/images/uhren/….jpg",
  "imageCount": 8
}
```

### Use cases

- **Price research** — pull a reference or model and see the full asking-price spread, split by condition and box-and-papers status
- **Dealer sourcing** — filter by `sellerCountry`, `condition` and `price` to spot listings worth a closer look
- **Market monitoring** — schedule it weekly on a brand or model and diff `priceAvg` and listing counts to catch a reference heating up or cooling off
- **Arbitrage screening** — compare Chrono24 asking prices against retail or another marketplace
- **Datasets** — export a whole brand's inventory with specs for analysis or a valuation model

### FAQ

**Why do other Chrono24 scrapers break?**
Chrono24 is behind Cloudflare and a bot-risk engine, and rotates its protection. A normal
request gets a 403. This Actor sends a real browser TLS fingerprint and retries on a fresh
residential IP, so it reads the same pages a visitor sees.

**Do I need a proxy or captcha solver?**
Apify Residential proxy is the default and required — no captcha solver needed. Datacenter
proxy usually gets blocked.

**Where does the data come from — a private API?**
No. Every Chrono24 brand, model and listing page embeds a JSON-LD block with the offer and
product data. Only public pages, no login.

**Can I filter (year, price, condition, box & papers…)?**
Apply the filters on chrono24.com, then paste that filtered URL into `urls`. The Actor
follows whatever the URL narrows to.

**Is this allowed?**
It reads only public Chrono24 brand, model and listing pages — the same pages any visitor
sees. It never logs in and never touches account, order or buyer data. Respect Chrono24's
terms and your local laws.

### Use it from an AI agent

This Actor is available as a tool over Apify's MCP server, so an AI agent (Claude,
ChatGPT, or any MCP client) can call it directly to pull Chrono24 watch listings
and pricing into a conversation or workflow.

### Notes

Reads only **public** Chrono24 pages. No login, no private data.

# Actor input Schema

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

Brand names to scrape, e.g. "rolex", "omega", "patek-philippe", "audemars-piguet". Each becomes a Chrono24 brand page and is paginated.

## `urls` (type: `array`):

Any chrono24.com page that lists watches - a brand page, a model page (…--mod…​.htm), a reference page, a filtered search, or a single listing (…--id…​.htm). Non-Chrono24 URLs are ignored.

## `maxListingsPerInput` (type: `integer`):

Stop after this many watches for each brand or URL (60 per page). Set 0 for no limit (hard cap 3000).

## `scrapeDetails` (type: `boolean`):

On: open every listing for the full record (reference number, year, movement, case material & size, box & papers, seller country). Off: faster and cheaper, but only title, price, currency, image and stock from the results page.

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

Chrono24 is behind Cloudflare. Apify Residential proxy (the default) is needed to get through reliably - datacenter IPs are usually blocked.

## Actor input object example

```json
{
  "brands": [
    "rolex",
    "omega",
    "tudor"
  ],
  "urls": [
    "https://www.chrono24.com/rolex/submariner--mod1240.htm",
    "https://www.chrono24.com/omega/speedmaster--mod172.htm"
  ],
  "maxListingsPerInput": 120,
  "scrapeDetails": true,
  "proxyConfiguration": {
    "useApifyProxy": true,
    "apifyProxyGroups": [
      "RESIDENTIAL"
    ]
  }
}
```

# Actor output Schema

## `listings` (type: `string`):

One row per watch for sale: brand, model, reference number, year, price, currency, condition, movement, case material & diameter, box & papers status, seller country and images.

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

listingsScraped, price min / avg / max, condition breakdown, box-and-papers count, top seller countries and brands seen.

## `overview` (type: `string`):

No description

# 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 = {
    "brands": [
        "rolex"
    ],
    "maxListingsPerInput": 120
};

// Run the Actor and wait for it to finish
const run = await client.actor("malek_oweis/chrono24-watch-listing-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 = {
    "brands": ["rolex"],
    "maxListingsPerInput": 120,
}

# Run the Actor and wait for it to finish
run = client.actor("malek_oweis/chrono24-watch-listing-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 '{
  "brands": [
    "rolex"
  ],
  "maxListingsPerInput": 120
}' |
apify call malek_oweis/chrono24-watch-listing-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,malek_oweis/chrono24-watch-listing-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/aVs6XnWecFadR56HC/builds/mVpC4mORe9BMkWPdc/openapi.json
