# CeX Scraper - Price Checker, Trade-In Prices & Stock (`s-r/cex-scraper`) Actor

Check CeX prices, trade-in cash and voucher values, Mint/Good/Working grades and stock in 10 countries. Look up products by EAN/UPC barcode, keyword or a CeX search URL and export one row per box to JSON, CSV or Excel for price tracking, reselling and catalogue matching.

- **URL**: https://apify.com/s-r/cex-scraper.md
- **Developed by:** [SR](https://apify.com/s-r) (community)
- **Categories:** E-commerce, Business
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

$2.00 / 1,000 products

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

## CeX Scraper: Price Checker, Trade-In Prices and Stock

CeX Scraper is a bulk CeX price checker for resellers, repair shops, comparison sites and analysts. It collects CeX selling prices, trade-in cash and voucher values, grades and stock status, using verified EAN or UPC barcodes, search keywords, or a search URL copied from a CeX storefront. Each dataset row represents one CeX box in one market and, where applicable, one condition grade.

### What CeX Scraper collects

The Actor supports the United Kingdom, Spain, Ireland, the Canary Islands, Portugal, Italy, Poland, Australia, Mexico and Malaysia. Prices stay in the currency of the selected storefront. UK results use GBP; Spain, Ireland, the Canary Islands, Portugal and Italy use EUR. Poland uses PLN, Australia AUD, Mexico MXN and Malaysia MYR. The country field uses GB for the UK and ES for the Canary Islands, while market preserves the storefront code.

CeX sells catalogue products rather than individual classified advertisements. A Sony headphone model can therefore appear three times, with separate A, B and C box IDs, prices and stock. Grade labels are Mint, Good and Working respectively. Products without a source grade have null grade and condition values. Stock can cover online orders, physical stores, or both.

For every box you get the selling price, the previous and first recorded price, the date of the last price change, the CeX trade-in cash and voucher values, stock flags for online and in-store availability, category, brand, rating and a working product link.

### Use cases

- **CeX price checker in bulk.** Paste hundreds of barcodes and read the current CeX selling price for every grade in one run, instead of looking up products one by one.
- **CeX trade-in prices for resellers.** Compare trade_in_cash and trade_in_voucher with what other buyers pay, and find the products where selling to CeX or buying from CeX leaves a margin.
- **CeX stock checker.** Track in_stock, in_stock_online and in_stock_store for a watch list, and get notified through an Apify schedule and webhook when a grade comes back in stock.
- **CeX price tracker.** Schedule the same input daily or weekly and store the dataset. previous_price, first_price and price_last_changed show how a box has moved, and your own history shows when.
- **Catalogue matching.** Join rows with a non-null gtin to your own product feed or to other retailers' barcode data, while keeping internal CeX SKUs separate.
- **Market research across countries.** Run the same search on the UK, Spain, Portugal or Australia storefront and compare second-hand price levels per market and currency.

### Input

Provide at least one of eans, searchTerms, startUrls or search_input. Inputs can be combined, with a maximum of 1,000 input positions per run. EAN inputs are processed first, followed by search terms and search URLs. The input_index field makes each result traceable to its position, including when the same input appears twice.

Use eans for barcode verification. It accepts a list of strings or text separated by commas or newlines. Codes must contain 8–14 digits. UPC and EAN representations with leading zeros are searched together, and a result is accepted only when the numeric prefix of its CeX box ID matches the requested barcode after leading-zero normalization. An unmatched code appears in the run summary and produces no chargeable row.

Use searchTerms for ordinary keyword searches, with a list of strings or one term per line. Keyword results are not filtered by a strict title matcher or barcode matcher. A barcode entered as a search term remains an ordinary text search; put it in eans when exact barcode verification matters.

Use startUrls for HTTPS search URLs on a supported CeX storefront. Category and facet selections are preserved, including categoryFriendlyName, Grade, productLineId, categoryIds and superCatId. A tilde between facet values means either value, such as Grade=B~C. Price ranges, all-stock availability and supported sortBy selections are also preserved. The URL host chooses the storefront; an explicitly conflicting market produces an input error.

market defaults to uk when no URL selects a storefront. maxItems defaults to 100 and applies separately to each search term or URL, with a maximum of 1,000. EAN lookups return all matching grades independently of maxItems. includeOutOfStock defaults to false for keyword searches, while EAN lookups include sold-out grades. minPrice and maxPrice constrain selling prices in the market currency for keyword and URL searches. Explicit filter options take precedence over corresponding URL choices.

sort accepts relevance, price_asc, price_desc, name_asc, name_desc, rating_desc and popularity_desc. An explicit sort overrides sortBy in a URL. CeX can return fewer matches for a sorted search than for relevance; this follows the storefront's own search behaviour. Aliases search_input, country_code, max_items, min_price and max_price are available. Canonical fields take precedence when both forms are supplied.

| Field | Type | Default | What it does |
|---|---|---|---|
| eans | list of strings | none | EAN/UPC codes, verified against the CeX box ID |
| searchTerms | list of strings | none | Keyword searches |
| startUrls | list of URLs | none | CeX search URLs with their filters |
| market | string | uk | uk, es, ie, ic, pt, it, pl, au, mx or my |
| maxItems | integer | 100 | Results per search term or URL, up to 1,000 |
| includeOutOfStock | boolean | false | Include sold-out boxes in keyword and URL searches |
| minPrice / maxPrice | number | none | Selling price range in the market currency |
| sort | string | relevance | Result order for keyword and URL searches |
| cursor | string | none | Continuation token from next_cursor; repeat the same input and settings |

#### Verified barcode example

This input was tested against real UK catalogue data:

```json
{"eans":["4548736132580"],"market":"uk"}
```

It resolves Sony WH-1000XM5 Black headphone boxes in grades A, B and C. Another tested code, 0195949052637, resolves AirPods Pro 2 box IDs that omit the initial zero. UPC 711719073208 resolves a box ID that includes an initial zero. These cases illustrate why checking both representations matters.

#### Search URL example

This URL was tested with the category and grade filters it carries:

```json
{"startUrls":["https://uk.webuy.com/search?stext=iphone+13&categoryFriendlyName=iPhone+13&Grade=C&sellPrice=200:250"],"maxItems":100}
```

### Output

The default dataset contains offers. Core fields include source, fetched_at, merchant, product_id, gtin, price, currency, country, condition, availability and url. Prices are numeric amounts, suitable for comparisons without parsing currency symbols. Product URLs point to the specific CeX box. The fetched_at timestamp records when the catalogue response was collected, not the date the product was first listed.

Additional fields include title, brand, image_url, market, grade, trade_in_cash, trade_in_voucher, previous_price, first_price, price_last_changed, in_stock, in_stock_online, in_stock_store, stock_quantity, collection_quantity, category, category_id, super_category, product_lines, rating, discontinued and first_stock_date. Every row also carries input, input_type, input_index and position. Source dates without a timezone remain unchanged. Trade-in fields are null when CeX does not display a buying price or does not allow buying that box.

Stock quantities may be capped by CeX. Treat a reported quantity as at least that many, not as an exact inventory count. Selling price, trade-in cash value and trade-in voucher value describe different transactions and should be compared separately.

#### Output example

The first row of the verified barcode example above, collected on 5 October 2026:

```json
{
  "market": "uk",
  "input": "4548736132580",
  "input_type": "ean",
  "input_index": 0,
  "position": 1,
  "fetched_at": "2026-10-05T15:43:06.323Z",
  "source": "cex-scraper",
  "merchant": "CeX",
  "product_id": "4548736132580A",
  "title": "Sony WH-1000XM5 Wireless Noise Canceling Over-Ears (Hard Case) - Black, A",
  "price": 210,
  "currency": "GBP",
  "country": "GB",
  "gtin": "4548736132580",
  "grade": "A",
  "condition": "Mint",
  "availability": "InStock",
  "url": "https://uk.webuy.com/product-detail?id=4548736132580A",
  "brand": "Sony",
  "image_url": "https://uk.static.webuy.com/product_images/Electronics/Headphones/4548736132580A_l.jpg",
  "trade_in_cash": 119,
  "trade_in_voucher": 144,
  "previous_price": 220,
  "first_price": 360,
  "price_last_changed": "2026-07-29 02:00:08",
  "in_stock": true,
  "in_stock_online": true,
  "in_stock_store": true,
  "stock_quantity": 30,
  "collection_quantity": 30,
  "category": "Headphones & Earphones",
  "category_id": "973",
  "super_category": "Electronics",
  "product_lines": ["Portable Entertainment", "Headphones"],
  "rating": 4.6,
  "discontinued": false,
  "first_stock_date": "2022-05-26 16:07:38"
}
```

The same run returned the B (Good, £180) and C (Working, £150) boxes as separate rows.

The summary and OUTPUT records contain delivered counts, warnings, missed EANs and search totals. not_found lists unmatched barcode inputs. searches is keyed by input_index and records the input, market, search index, total hits and returned count. Large input lists are continued automatically. Dataset identity includes the input position, market and product ID, so the same box returned for two inputs remains two attributable rows.

### CeX Scraper compared with other options

| Option | Good for | What you give up |
|---|---|---|
| Checking prices on the CeX website | A handful of products | No export, one product and one market at a time |
| Consumer CeX price checker and tracker sites | Browsing price changes in the UK | No structured feed of your own list, no barcode verification, usually one market |
| Writing your own scraper | Full control | Building and maintaining storefront access, pagination and barcode matching yourself |
| CeX Scraper | Bulk lookups, scheduled tracking, exports | Results are limited to what CeX shows in its catalogue search |

What sets this Actor apart is exact barcode mode: a barcode only returns boxes whose ID matches that EAN or UPC, so a lookup never fills your sheet with similar-looking products. Grades stay separate, prices are numbers, gtin is only filled when the barcode passes its GS1 check digit, and search URLs keep the filters you selected on the storefront.

### Pricing

The proposed starting price is $0.002 per product result, or $2 per 1,000 rows. The Actor charges the product event once per delivered row. There is no run-start charge in this model. Empty searches and missed barcodes deliver no rows and incur no product charge. The current price displayed on the Actor page is the applicable price when running it.

As an example, 500 barcodes that each resolve three grades deliver 1,500 rows, which is $3.00 at the starting price. 50 of those barcodes not found at CeX cost nothing.

Users on the free plan receive up to 10 rows per run. Paying users can collect their requested results. OUTPUT and summary expose freeTierCapped, freeTierDelivered, userIsPaying and free_tier_remaining. The remaining count is 0–10 for free users and -1 for paying users. These limits apply across all inputs in the run, rather than resetting for each keyword.

### Limits and interpretation

CeX restricts each search to its first 1,000 matches. Narrow broad queries with categories, grades or price bands. This is not a full catalogue export. Dutch and Indian storefronts are currently excluded because the observed catalogues have no online stock. Search names remain in the language used by the storefront.

Not every CeX box has a barcode. Phones, laptops and consoles often use internal SKU identifiers. Their gtin field is null, while the original box ID remains in product_id. A numeric box ID is exposed as gtin only when it has a supported barcode length and passes its GS1 check digit. Do not join internal SKUs to another retailer's barcode catalogue by guessing.

### FAQ

#### Can I use this as a CeX price checker for a list of products?

Yes. Put the barcodes in eans, or the product names in searchTerms, and run once. Every grade comes back as its own row with price, trade-in values and stock, ready to export.

#### Can I compare grades of the same product?

Yes. Each grade has its own row, price, availability and box ID. Group rows by a non-null gtin and market to compare those offers, while keeping grade separate.

#### Why did my barcode produce no results?

CeX may not carry that product, or may represent it with an internal SKU. Exact EAN mode intentionally rejects unrelated keyword matches. Check not_found in the summary; missed inputs are free.

#### Does this include out-of-stock products?

EAN lookups do, allowing you to see all known grades. Keyword and URL searches default to available stock, unless includeOutOfStock is enabled or the URL selects all stock.

#### Does CeX have an official API?

CeX does not offer a documented public developer API for its catalogue. Searches for "CeX API" mostly lead to an unrelated cryptocurrency exchange. This Actor gives you the CeX catalogue as a dataset you can query through the Apify API, with JSON, CSV and Excel exports.

#### How do I track CeX prices or stock over time?

Save your input as a task and add an Apify schedule, for example daily. Each run writes a new dataset; compare price and in_stock between runs, or use a webhook to send changes to your own system.

#### Can I export the results?

Yes. Use Apify dataset exports such as JSON, CSV or Excel. Numeric prices, stable box IDs and input context support scheduled comparisons and catalogue joins. Always keep currency and market alongside each price.

# Actor input Schema

## `eans` (type: `array`):

EAN/UPC/GTIN codes, as a list or comma/newline-separated string. 8–14 digits. Box IDs are verified; missed codes are free.

## `searchTerms` (type: `array`):

Search terms as a list or newline-separated string. Returns keyword results without barcode or title matching.

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

HTTPS CeX /search URLs, as strings or {url} objects. Preserves category, facets, price range and sorting. Host selects the market; an explicitly conflicting market is rejected.

## `market` (type: `string`):

CeX market; defaults to uk when no search URL chooses a market. Netherlands and India are unavailable.

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

Maximum rows per search term or URL, default 100. EAN mode returns all verified grades independently of this setting.

## `includeOutOfStock` (type: `boolean`):

Include sold-out keyword results; default false. EAN lookups always include sold-out grades, following the original parser.

## `sort` (type: `string`):

Optional sort order; overrides sortBy from a search URL. CeX sorted searches can have a different result set.

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

Minimum selling price in the market currency for keyword and URL searches.

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

Maximum selling price in the market currency for keyword and URL searches.

## `cursor` (type: `string`):

Continuation token from next_cursor. Repeat the same input and settings. Apify follows it automatically.

## `search_input` (type: `array`):

Alias accepting search terms and CeX search URLs, one per line or as a list. Barcodes here are ordinary keyword searches; use eans for verification.

## `country_code` (type: `string`):

Alias for market, used when market is absent.

## `max_items` (type: `integer`):

Alias for maxItems, used when maxItems is absent.

## `min_price` (type: `number`):

Alias for minPrice, used when minPrice is absent.

## `max_price` (type: `number`):

Alias for maxPrice, used when maxPrice is absent.

## Actor input object example

```json
{
  "eans": [
    "4548736132580"
  ]
}
```

# Actor output Schema

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

Selling prices, grades and stock.

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

Counts, searches, missed codes and free-tier remainder.

## `output` (type: `string`):

Delivery, billing and continuation status.

# 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 = {
    "eans": [
        "4548736132580"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("s-r/cex-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 = { "eans": ["4548736132580"] }

# Run the Actor and wait for it to finish
run = client.actor("s-r/cex-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 '{
  "eans": [
    "4548736132580"
  ]
}' |
apify call s-r/cex-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,s-r/cex-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/rgrX24W3aXMpdb2oh/builds/hBh9eohHZJxUN5J5Q/openapi.json
