# Cardmarket Listings Scraper (`phantom_coder/cardmarket-listings-scraper`) Actor

Scrape all seller listings from any Cardmarket card page — condition, language, quantity, price in EUR/USD. Optional Fair Value Analysis for Scarlet & Violet and Mega Evolution sets adds AI pricing, PSA data, gem rate, and deal score.

- **URL**: https://apify.com/phantom\_coder/cardmarket-listings-scraper.md
- **Developed by:** [Phantom Coder](https://apify.com/phantom_coder) (community)
- **Categories:** E-commerce, AI, Automation
- **Stats:** 25 total users, 7 monthly users, 97.0% runs succeeded, 2 bookmarks
- **User rating**: 5.00 out of 5 stars

## Pricing

from $2.50 / 1,000 card listings

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/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

## Cardmarket listings scraper

Scrape every individual seller listing from any Cardmarket product page - one row per offer, with seller name, condition, language, quantity, and price in EUR and USD.

Optionally enrich each listing with **Fair Value Analysis**: an AI-powered valuation from a specialized pricing data model that estimates what a card is worth, how it compares to PSA-graded copies, and whether a listing is trading above or below fair value.

***

### Who is this for

- **TCG investors** hunting undervalued copies before flipping or grading - sort by `discountVsFairValuePct` descending and surface listings trading 20%+ below model value in seconds
- **Graders** checking whether the raw market price justifies the cost of a PSA submission - compare `price` against `psa10PriceUsd` and `gemRatePct` to estimate expected return
- **Resellers** monitoring specific cards daily for arbitrage opportunities without manually refreshing Cardmarket
- **Collectors** setting price alerts via Make or Zapier when a card drops below a target price in EUR

No Cardmarket account required. Works on any public product page.

***

### Why it's different

The six other Cardmarket Actors on Apify Store all scrape the weekly price trend page - one aggregated number per card, suitable for broad market research. This Actor scrapes the **individual seller listing table** - one row per offer, with the seller name, condition grade, language, quantity, and asking price.

That distinction matters when you are making purchasing decisions. A card with a trend price of €150 might have a NM English copy listed at €118 from a Power Seller in Germany. The trend page will never show you that. This Actor will.

With Fair Value Analysis enabled, each listing also gets a deal score: how far the asking price sits below the model's estimate of fundamental value. A `discountVsFairValuePct` of +24 means the seller is asking 24% below what comparable graded sales suggest the card is worth in raw form - that is the signal no trend scraper can give you.

***

### What you get

**Every listing row includes:**

- Card name, seller username, condition (MT/NM/EX/GD/LP/MP/HP/PO), language, and quantity
- Price in EUR (as listed on Cardmarket), converted to USD at the live exchange rate
- Seller comment when the seller added a note to the listing (condition details, grading info, shipping notes)
- Direct link to the product page

**With Fair Value Analysis enabled (Scarlet & Violet and Mega Evolution sets):**

- `fairValueEur` / `fairValueUsd` - pricing data model's estimate of what the card is worth
- `discountVsFairValuePct` - how far the listing is below (or above) model value; positive = below = potential deal
- `rawPriceEur` / `rawPriceUsd` - blended current market price from recent comparable sales
- `discountVsRawPct` - how the listing compares to spot market price
- `psa9PriceUsd` / `psa10PriceUsd` - estimated PSA 9 and PSA 10 grade prices
- `gemRatePct` - percentage of submitted copies that graded PSA 10
- `psa10Pop` / `totalPop` - PSA 10 population and total graded supply
- `price1dChangePct` - 1-day price momentum
- `price7dVs30dChangePct` - 7-day price trend vs the 30-day average

***

### How to use

<ol>
  <li>Open the Cardmarket product page for the card you want to track (e.g. <code>cardmarket.com/en/Pokemon/Products/Singles/151/Blastoise-ex-V3-MEW200</code>).</li>
  <li>Copy the URL and paste it into the <strong>Cardmarket product URL</strong> field.</li>
  <li>Set your minimum condition, language, and price filters as needed.</li>
  <li>Run the Actor. All listing pages are crawled automatically up to your <strong>Max results</strong> limit.</li>
  <li>In the Output tab, sort by <strong>Deal vs FV (%)</strong> descending to surface the listings trading furthest below fair value.</li>
</ol>

> ⚠️ **Getting 0 results is completely normal.** It means no listings matched your filters (condition, language, price range) at the time of the run - not that the Actor failed. Try relaxing the condition filter or removing the language filter to confirm there are listings available.

***

### Input configuration

| Field | Type | Default | Description |
|---|---|---|---|
| `productUrl` | String | required | Product page URL for the specific card. |
| `minCondition` | Select | NM | Only return listings at or above this quality: MT, NM, EX, GD, LP, MP, HP, or PO. |
| `language` | Select | Any language | Filter by card language (English, French, German, Spanish, Italian, Simplified Chinese, Japanese, Portuguese, Russian, Korean). |
| `minPrice` | Number | — | Only return listings at or above this price in EUR. |
| `maxPrice` | Number | — | Only return listings at or below this price in EUR. |
| `sellerCountry` | Select | Any country | Only return listings from sellers in this country. Covers all major Cardmarket seller countries across Europe. |
| `maxResults` | Integer | 10 | Maximum listings to return. Range: 1 to 500. |
| `enableFairValue` | Boolean | false | Enable the Fair Value Analysis add-on. Charged once per run when data is available. Covers Scarlet & Violet and Mega Evolution sets only. |
| `isSigned` | Boolean | false | Advanced filter: signed cards only. |
| `isAltered` | Boolean | false | Advanced filter: altered art only. |
| `isFirstEd` | Boolean | false | Advanced filter: first edition only. |
| `isPlayset` | Boolean | false | Advanced filter: playset listings only (4 copies). |
| `sellerType` | Select | Any seller | Advanced filter: private sellers only, or commercial sellers only. |

**Example input:**

```json
{
  "productUrl": "https://www.cardmarket.com/en/Pokemon/Products/Singles/151/Blastoise-ex-V3-MEW200",
  "minCondition": "NM",
  "language": "English",
  "minPrice": 100,
  "maxPrice": 300,
  "sellerCountry": "DE",
  "maxResults": 50,
  "enableFairValue": true
}
```

***

### Output

**Base listing (all sets):**

```json
{
  "cardName": "Blastoise ex MEW #200",
  "sellerName": "seller_username",
  "condition": "NM",
  "language": "English",
  "quantity": 1,
  "price": 145.00,
  "currency": "EUR",
  "priceUsd": 159.50,
  "sellerComment": "Off center. NM-EX. Fast shipping.",
  "eurUsdRate": 1.10,
  "productUrl": "https://www.cardmarket.com/en/Pokemon/Products/Singles/151/Blastoise-ex-V3-MEW200"
}
```

**Listing with Fair Value Analysis (Scarlet & Violet and Mega Evolution sets):**

```json
{
  "cardName": "Blastoise ex MEW #200",
  "sellerName": "seller_username",
  "condition": "NM",
  "language": "English",
  "quantity": 1,
  "price": 145.00,
  "currency": "EUR",
  "priceUsd": 159.50,
  "fairValueEur": 200.00,
  "fairValueUsd": 220.00,
  "discountVsFairValuePct": 27.5,
  "rawPriceEur": 159.09,
  "rawPriceUsd": 175.00,
  "discountVsRawPct": 8.9,
  "price1dChangePct": -0.5,
  "price7dVs30dChangePct": 2.1,
  "gemRatePct": 68.5,
  "psa10Pop": 1240,
  "totalPop": 2840,
  "psa9PriceUsd": 280.00,
  "psa10PriceUsd": 650.00,
  "eurUsdRate": 1.10,
  "gemRateDate": "2026-05-01",
  "sellerComment": "Off center. NM-EX. Fast shipping.",
  "productUrl": "https://www.cardmarket.com/en/Pokemon/Products/Singles/151/Blastoise-ex-V3-MEW200"
}
```

***

### Understanding the data

#### Fair value and deal score

`fairValueEur` and `fairValueUsd` are the pricing data model's estimate of what the raw card is worth, derived from graded card sales (PSA 9 and PSA 10), historical price trends, and grading population supply. It is a fundamental value estimate updated on a rolling basis, not a live bid/ask price.

`discountVsFairValuePct` measures how far the listing price is from that estimate:

- **Positive** = listing is below model value - a potential deal. +27.5 means you are paying 27.5% less than the model says the card is worth.
- **Negative** = listing is above model value - seller is asking a premium.

`rawPriceEur` and `rawPriceUsd` are the blended current market price from recent comparable raw sales - the spot price where the card is actually trading today.

`discountVsRawPct` measures how the listing compares to that spot price:

- **Positive** = listing is below current market - a relative bargain among active sellers.
- **Negative** = listing is above current market - seller is asking more than recent trades.

**Reading both together:**

| `discountVsFairValuePct` | `discountVsRawPct` | What it means |
|---|---|---|
| Positive | Positive | Below model value and below market - strongest buy signal |
| Positive | Negative | Below model value but above market - market itself is cheap vs the model; opportunity if you trust the model |
| Negative | Positive | Above model value but below market - market is expensive vs the model; consider waiting |
| Negative | Negative | Above both - overpriced listing |

#### Grading data

`gemRatePct` is the percentage of submitted copies that have achieved PSA 10. A low gem rate (e.g. below 30%) means the card is difficult to grade to a perfect 10, which increases the scarcity and value of existing PSA 10 copies. A high gem rate means PSA 10s are more abundant and easier to produce.

`psa10Pop` is the total number of PSA 10 copies on record. Combined with `gemRatePct`, this gives a picture of supply: a low pop with a low gem rate signals a genuinely scarce graded card.

#### Price momentum

`price1dChangePct` shows whether the raw market price moved up or down in the last day.

`price7dVs30dChangePct` compares the 7-day average price to the 30-day average. A positive value means recent prices are running above the monthly average - the card is gaining momentum. A negative value means it is softening.

#### Condition codes

| Code | Condition |
|---|---|
| MT | Mint |
| NM | Near Mint |
| EX | Excellent |
| GD | Good |
| LP | Light Played |
| MP | Moderately Played |
| HP | Heavily Played |
| PO | Poor |

***

### Common use cases

**Find undervalued Special Illustration Rares**

Run the Actor on a SIR product page with `enableFairValue: true` and `minCondition: NM`. Sort the output by `discountVsFairValuePct` descending. Listings with a discount above 15 are trading meaningfully below the model's estimate of fair value - a concrete starting point for a buy decision.

**Grading return calculator**

Set `enableFairValue: true` and look at `psa10PriceUsd`, `gemRatePct`, and the listing `price`. If `psa10PriceUsd` is $650, `gemRatePct` is 68, and a NM English copy is listed at $145, the expected value of a submission is roughly $650 × 0.68 - grading cost. Listings where that math works at current prices appear in seconds.

**Daily price monitoring**

Schedule the Actor to run once per day with `maxResults: 10`. This gives you the cheapest NM listings at the current moment for a quick price check. At $0.05 per run on the free plan, monitoring 10 cards daily costs around $0.50/month.

**Build a watchlist with Make or Zapier**

Set up a scenario that loops through a list of Cardmarket URLs, triggers one Actor run per card, and appends results to a Google Sheet or Airtable base. Filter rows where `discountVsFairValuePct > 15` to surface only the listings worth acting on.

**Spot momentum before the market moves**

Filter for cards where `price7dVs30dChangePct` is positive and `discountVsFairValuePct` is also positive - cards gaining price momentum that have not yet priced in the move at the individual seller level.

***

### FAQ

**Do I need a Cardmarket account or API key?**
No. The Actor works entirely on public Cardmarket data - no login, no credentials required.

**Which sets support Fair Value Analysis?**
All Scarlet & Violet sets (from the base set through current releases) and all Mega Evolution sets. Cards from older sets (XY, Sun & Moon, etc.) return the full listing data without the Fair Value enrichment fields.

**Why am I getting 0 results?**
The most common cause is filters that are stricter than the available listings - for example, filtering for English NM on a card that only has Italian listings. Try removing the language filter or relaxing the condition to EX to confirm there are listings available. 0 results is a clean exit, not a failure.

**What is the difference between Fair Value and Raw Price?**
`fairValueEur` is the model's estimate of the card's fundamental worth based on graded card sales and supply data - it is forward-looking and changes slowly. `rawPriceEur` is the blended current market price from recent raw sales - it reflects where the card is actually trading today. The two diverge when the market is moving: if `rawPriceEur` is significantly below `fairValueEur`, the market is temporarily cheap relative to fundamentals.

**Can I scrape multiple cards in one run?**
No. The Actor scrapes one product page per run. To monitor a list of cards, use Apify scheduling with one task per card, or trigger runs in a loop from Make or Zapier.

***

### Limitations

1. **Fair Value Analysis is not available for all sets.** It covers Scarlet & Violet (base set through current releases) and Mega Evolution sets. Cards from older sets return full listing data without enrichment fields.
2. **One card per run.** The Actor scrapes a single product page per run. To monitor a list of cards, use Apify's scheduling feature with one task per card, or loop through URLs using Make or Zapier.
3. **Prices change continuously.** Each run reflects the live state of Cardmarket at that moment. A listing shown as a deal may sell before you act on it.
4. **Seller listings only.** The Actor returns individual seller offers, not Cardmarket's aggregated trend data. It does not scrape pack prices, sealed product, or categories - only Singles product pages.

***

### Pricing

This Actor uses Pay-Per-Event (PPE) pricing - you pay only for what you actually receive.

| Event | Free | Starter | Scale | Business |
|---|---|---|---|---|
| Actor start | $0.00005 | $0.00005 | $0.00005 | $0.00005 |
| Card listing | $0.005 | $0.004 | $0.003 | $0.0025 |
| Fair Value Analysis | $0.070 | $0.060 | $0.050 | $0.040 |

**Typical run costs:**

| Run type | Free plan | Starter | Scale |
|---|---|---|---|
| 50 listings, no Fair Value | $0.25 | $0.20 | $0.15 |
| 50 listings + Fair Value | $0.32 | $0.26 | $0.20 |
| 10 listings + Fair Value (daily monitor) | $0.12 | $0.10 | $0.08 |

**Typical monthly cost (Starter plan, $0.004/listing):**

- Monitor 10 cards daily (300 runs/month, 10 listings each): **$12.00/month**
- Scan a watchlist of 50 cards once weekly: **$0.80/month**
- One-off bulk scan of 500 listings across 10 cards: **$2.00**

**vs. other Cardmarket Actors:** The six other Cardmarket Actors on Apify Store all scrape aggregated weekly trend pages - a single price per card, not individual seller rows - at $0.001 per result. This Actor returns actionable purchasing data (seller, condition, language, quantity, and price per offer) at $0.005 per listing on the free plan, with optional Fair Value enrichment that no competing Actor provides.

You can cap spending per run using the `ACTOR_MAX_TOTAL_CHARGE_USD` limit in your Apify integration settings.

***

### Output field reference

#### Listing fields (all sets)

| Field | What it contains |
|---|---|
| `cardName` | Card name parsed from the Cardmarket URL slug, including set code and card number (e.g. `Blastoise ex MEW #200`) |
| `sellerName` | Cardmarket username of the seller |
| `condition` | Condition grade: MT, NM, EX, GD, LP, MP, HP, or PO |
| `language` | Card language as listed on Cardmarket (English, French, German, Italian, etc.) |
| `quantity` | Number of copies available in this listing |
| `price` | Asking price in EUR as shown on Cardmarket |
| `currency` | Always `EUR` |
| `priceUsd` | `price × live EUR/USD rate` |
| `eurUsdRate` | EUR/USD exchange rate used for conversion, fetched at run time |
| `sellerComment` | Seller's note on the listing (condition details, grading info, shipping terms). `null` when no comment set. |
| `productUrl` | Full URL to the Cardmarket product page |

#### Fair Value Analysis fields (Scarlet & Violet and Mega Evolution sets only)

| Field | What it measures |
|---|---|
| `fairValueEur` | Model's estimate of the card's fundamental raw value in EUR, derived from graded card sales and supply data |
| `fairValueUsd` | Same estimate in USD |
| `discountVsFairValuePct` | `(fairValue - price) / fairValue × 100` — positive means the listing is below model value (buy signal); negative means above |
| `rawPriceEur` | Blended current market price from recent comparable raw sales in EUR - the spot price where the card is actively trading |
| `rawPriceUsd` | Same spot price in USD |
| `discountVsRawPct` | `(rawPrice - price) / rawPrice × 100` — how the listing compares to the current market spot price |
| `psa9PriceUsd` | Estimated PSA 9 grade price in USD based on recent graded sales |
| `psa10PriceUsd` | Estimated PSA 10 grade price in USD based on recent graded sales |
| `gemRatePct` | Percentage of submitted copies that achieved PSA 10 — lower values signal a harder-to-grade card |
| `psa10Pop` | Total PSA 10 copies on record |
| `totalPop` | Total graded copies (all grades) on record |
| `price1dChangePct` | 1-day percentage change in the raw market price |
| `price7dVs30dChangePct` | `(7-day avg price / 30-day avg price - 1) × 100` — positive means the card is gaining momentum |
| `gemRateDate` | Date the grading population data was last updated |

***

### Support

Questions or issues? Open a ticket in the **Issues** tab on the Actor page.

# Actor input Schema

## `productUrl` (type: `string`):

Cardmarket product page URL for the specific card you want to scrape.

## `minCondition` (type: `string`):

Only return listings at or better than this condition.

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

Only return listings in this language.

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

Only return listings at or above this price in EUR.

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

Only return listings at or below this price in EUR.

## `sellerCountry` (type: `string`):

Only show listings from sellers in this country.

## `maxResults` (type: `integer`):

Maximum number of listings to return per run.

## `enableFairValue` (type: `boolean`):

Enrich each listing with an AI-powered fair value estimate, blended market price, PSA grade prices, price momentum, gem rate, and PSA population data. Available for Scarlet & Violet and Mega Evolution sets.

## `isSigned` (type: `boolean`):

Only return listings for signed cards.

## `isAltered` (type: `boolean`):

Only return listings for altered art cards.

## `isFirstEd` (type: `boolean`):

Only return first edition listings.

## `isPlayset` (type: `boolean`):

Only return playset listings (4 copies).

## `sellerType` (type: `string`):

Filter by seller type.

## Actor input object example

```json
{
  "productUrl": "https://www.cardmarket.com/en/Pokemon/Products/Singles/151/Blastoise-ex-V3-MEW200",
  "minCondition": "NM",
  "language": "any",
  "sellerCountry": "any",
  "maxResults": 10,
  "enableFairValue": false,
  "isSigned": false,
  "isAltered": false,
  "isFirstEd": false,
  "isPlayset": false,
  "sellerType": "any"
}
```

# Actor output Schema

## `dataset` (type: `string`):

All scraped seller listings

# 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 = {
    "productUrl": "https://www.cardmarket.com/en/Pokemon/Products/Singles/151/Blastoise-ex-V3-MEW200"
};

// Run the Actor and wait for it to finish
const run = await client.actor("phantom_coder/cardmarket-listings-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 = { "productUrl": "https://www.cardmarket.com/en/Pokemon/Products/Singles/151/Blastoise-ex-V3-MEW200" }

# Run the Actor and wait for it to finish
run = client.actor("phantom_coder/cardmarket-listings-scraper").call(run_input=run_input)

# Fetch and print Actor results from the run's dataset (if there are any)
print("💾 Check your data here: https://console.apify.com/storage/datasets/" + run["defaultDatasetId"])
for item in client.dataset(run["defaultDatasetId"]).iterate_items():
    print(item)

# 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/python/docs/quick-start

```

## CLI example

```bash
echo '{
  "productUrl": "https://www.cardmarket.com/en/Pokemon/Products/Singles/151/Blastoise-ex-V3-MEW200"
}' |
apify call phantom_coder/cardmarket-listings-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "command": "npx",
            "args": [
                "mcp-remote",
                "https://mcp.apify.com/?tools=phantom_coder/cardmarket-listings-scraper",
                "--header",
                "Authorization: Bearer <YOUR_API_TOKEN>"
            ]
        }
    }
}

```

## OpenAPI specification

Download the OpenAPI definition: https://api.apify.com/v2/actors/8nK78EPfraXf9MAg9/builds/Is1x3Iunljwg3ru8p/openapi.json
