# Transfermarkt Market Value Scraper: Value Change Alerts (`accountable_eel/transfermarkt-player-value-lookup`) Actor

Transfermarkt market value scraper and tracker: look up players by link, id or name, whole squads, a league's top table or the most valuable players. Get value changes, club changes and new top-table entrants posted to Discord, Slack or Telegram. Sporting data only. No login.

- **URL**: https://apify.com/accountable_eel/transfermarkt-player-value-lookup.md
- **Developed by:** [Adriana Voss](https://apify.com/accountable_eel) (community)
- **Categories:** Sports, Automation
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $6.08 / 1,000 player returneds

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?

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

## Transfermarkt Market Value Scraper: Value Change Alerts

Look up the Transfermarkt market value of any list of players, whole squads, a league's most valuable players, or the world's top table. Switch on monitoring and get a message in Discord, Slack or Telegram when a player's value moves, a player changes club, or someone enters the top table. Sporting data only. No login.

### What it does

- **Players.** Paste Transfermarkt profile links, the number at the end of a link, or just names. You get club, position, age, nationality, market value in euros and the contract end date; the previous value and change in percent come with monitoring or the history option.
- **Squads and tables.** Paste a club link for its whole squad, a league link for that league's most valuable players, or tick "Add the world's most valuable players".
- **Monitoring.** Tick "Only return players that changed since the last run" and schedule the actor. Unchanged players cost nothing: you are billed only for the players that moved.
- **Value history.** Tick "Include the value history and previous value" for Transfermarkt's full market value timeline (date, value, club at the time), the previous value and the change in percent for every player you listed. It needs a second request per player.

A miss (a name Transfermarkt does not know, a bot check) comes back as a row with `"found": false` and is never charged.

### How to use

1. **In the Apify Console.** Open the actor page and click **Start** — the `players` field is already pre-filled with a working example. Results land in the run's dataset as soon as each item is found.
2. **Via the API.** Call it directly with a POST request — no Console needed once you have an API token:
   ```bash
   curl "https://api.apify.com/v2/acts/accountable_eel~transfermarkt-player-value-lookup/run-sync-get-dataset-items?token=<YOUR_TOKEN>" \
     -X POST \
     -H "Content-Type: application/json" \
     -d '{"players":["https://www.transfermarkt.com/lamine-yamal/profil/spieler/937958","https://www.transfermarkt.com/erling-haaland/profil/spieler/418560","https://www.transfermarkt.com/kylian-mbappe/profil/spieler/342229","https://www.transfermarkt.com/michael-olise/profil/spieler/566723","https://www.transfermarkt.com/jude-bellingham/profil/spieler/581678"]}'
   ```
3. **On a schedule.** Save this actor as an Apify **Task** with the input you want, then add a **Schedule** (hourly, daily, weekly) so it runs on its own — no server of your own required.

### Input

```json
{
  "players": [
    "https://www.transfermarkt.com/lamine-yamal/profil/spieler/937958",
    "https://www.transfermarkt.com/erling-haaland/profil/spieler/418560",
    "https://www.transfermarkt.com/kylian-mbappe/profil/spieler/342229",
    "https://www.transfermarkt.com/michael-olise/profil/spieler/566723",
    "https://www.transfermarkt.com/jude-bellingham/profil/spieler/581678"
  ]
}
```

One player per line: a Transfermarkt profile link, the number at the end of that link, or just a name such as "Lamine Yamal". Names use Transfermarkt's own search and take the first player it lists. Add whole squads, a league's top table or the world's most valuable players with the fields below. No login required. Accepted formats: https://www.transfermarkt.com/erling-haaland/profil/spieler/418560, 418560, Lamine Yamal.

An example that mixes a player list, one squad and the top table:

```json
{
  "players": ["https://www.transfermarkt.com/erling-haaland/profil/spieler/418560", "Lamine Yamal"],
  "clubs": ["https://www.transfermarkt.com/manchester-city/startseite/verein/281"],
  "topValue": true,
  "maxItems": 30,
  "includeHistory": true
}
```

### Output

One row per player, for example:

| query | found | status | playerId | name | club | position | age | nationality | marketValueEur | previousValueEur | valueChangePct | previousValueSource | contractExpires | changeType | changeDetail | valueHistory | url | checkedAt | scrapedAt |
| --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- |
| https://www.transfermarkt.com/erling-haaland/profil/spieler/418560 | false | BLOCKED | <player id> | <player> | <club> | <position> | <age> | <nationality> | \<market value (eur)> | \<previous value (eur)> | \<change (%)> | <previous value from> | <contract expires> | <change type> | <what changed> | <value history> | <transfermarkt page> | <checked at> | 2026-10-29T22:30:26.744Z |

| Field | Meaning |
| --- | --- |
| `marketValueEur` | Current market value in euros (a Transfermarkt community estimate). |
| `previousValueEur`, `valueChangePct` | The value before this one and the change in percent. With monitoring on and an earlier run, this is the value you saw last time (`previousValueSource: last-run`). Transfermarkt's own previous valuation (`transfermarkt-history`) is read only when you tick "Include the value history" or when monitoring sees a player for the first time; otherwise both fields are empty. |
| `contractExpires` | Contract end date from the player's page. Empty for players that come from a squad or table (those lists do not carry it). |
| `changeType`, `changeDetail` | Monitoring runs only: `baseline` (first time seen), `value-change`, `club-change`, `new-entrant` or `unchanged`, with the old and new value in words. |
| `valueHistory` | Only when "Include the value history" is ticked. |
| `found`, `status`, `message` | `OK`, or `NOT_FOUND`, `BLOCKED`, `BAD_FORMAT`, `PARSE_CHANGED` with a plain explanation. |

### Alert me when a player's value changes

1. **Start with your list.** Put the players (or a club link, or the top table) into the input and tick **Only return players that changed since the last run**. Give the watchlist a name if you will edit the list later. Run it once: it saves every current value as the baseline.
2. **Add the alert link.** Create a webhook in your Discord channel (Channel settings, Integrations, Webhooks), a Slack incoming webhook, or a Telegram bot link, and paste it into **Send alerts to**. The link is stored encrypted and never written to the results.
3. **Schedule it.** Save the input as an Apify Task and add a Schedule (daily or weekly). From the second run on, each value change, club change and new top-table entrant arrives as one message with the old and new value; a quiet run returns nothing and bills only the start fee.

### Example runs

- **Transfermarkt market value for a list of players.** Five profile links in `players`; add `includeHistory` for the timeline.
- **Transfermarkt most valuable players by league.** One league link in `clubs` (for example `https://www.transfermarkt.com/premier-league/marktwerte/wettbewerb/GB1`) and `maxItems` 25.
- **Player value change alert to Discord.** The same players, `deltaMode` on, `minChangePct` 5, and your Discord webhook in `notifyUrl`.

### Limits

- **Sporting data only.** No dates of birth, places of birth, agents, family, social media or photos are read or returned.
- **Market values are Transfermarkt community estimates**, not transfer fees, and Transfermarkt updates them in steps a few times a year, so most days nothing changes.
- **Squads and tables carry less.** Rows from a club or league link have no contract date and no value history; monitoring still compares their value and club between runs.
- **Names take the first search hit.** A common name can match someone else: use the profile link or id for certainty.
- **Pace.** Pages are fetched one at a time, about every 1.5 seconds: one request per listed player, two with the history option. A 100-player list takes several minutes. If Transfermarkt answers with a rate limit or a bot check, the run stops asking, returns the remaining entries as free `BLOCKED` rows and charges nothing for them.
- **Terms.** Transfermarkt's terms restrict automated access to its content; you are responsible for how you use the data.

* **Player returned**: $8 per 1,000 players

Plus a $0.002 start fee per run. Each event above is billed independently, only when it actually returns data — misses (`found:false`) are never charged.

This actor runs synchronously over plain HTTP — call it directly from a script, a workflow tool, or an AI agent, no Apify Console needed once you have an API token.

```bash
curl "https://api.apify.com/v2/acts/accountable_eel~transfermarkt-player-value-lookup/run-sync-get-dataset-items?token=<YOUR_TOKEN>" \
  -X POST \
  -H "Content-Type: application/json" \
  -d '{"players":["https://www.transfermarkt.com/lamine-yamal/profil/spieler/937958","https://www.transfermarkt.com/erling-haaland/profil/spieler/418560","https://www.transfermarkt.com/kylian-mbappe/profil/spieler/342229","https://www.transfermarkt.com/michael-olise/profil/spieler/566723","https://www.transfermarkt.com/jude-bellingham/profil/spieler/581678"]}'
```

**n8n.** Add an HTTP Request node: Method `POST`, URL `https://api.apify.com/v2/acts/accountable_eel~transfermarkt-player-value-lookup/run-sync-get-dataset-items?token=<YOUR_TOKEN>`, Body Content Type `JSON`, JSON Body `{"players":["https://www.transfermarkt.com/lamine-yamal/profil/spieler/937958","https://www.transfermarkt.com/erling-haaland/profil/spieler/418560","https://www.transfermarkt.com/kylian-mbappe/profil/spieler/342229","https://www.transfermarkt.com/michael-olise/profil/spieler/566723","https://www.transfermarkt.com/jude-bellingham/profil/spieler/581678"]}` (swap in an expression from an earlier node for a real value).

**Clay.** Add an "HTTP API" column: Method `POST`, URL `https://api.apify.com/v2/acts/accountable_eel~transfermarkt-player-value-lookup/run-sync-get-dataset-items?token=<YOUR_TOKEN>`, Body `{"players":["{{player}}"]}`, mapping the row's player into the `players` array.

**MCP.** In Claude, Cursor, or any MCP client with the Apify MCP server, ask for "Transfermarkt Scraper: Market Value & Change Alerts" — the agent will find and run this actor.

# Actor input Schema

## `players` (type: `array`):

One player per line: a Transfermarkt profile link, the number at the end of that link, or just a name such as "Lamine Yamal". Names use Transfermarkt's own search and take the first player it lists. Add whole squads, a league's top table or the world's most valuable players with the fields below. No login required. Accepted formats: https://www.transfermarkt.com/erling-haaland/profil/spieler/418560, 418560, Lamine Yamal. You're only charged for the ones we actually find — a miss costs nothing.

## `clubs` (type: `array`):

Optional. One link per line, copied from transfermarkt.com: a club (https://www.transfermarkt.com/manchester-city/startseite/verein/281) adds its whole squad with market values; a league (https://www.transfermarkt.com/premier-league/marktwerte/wettbewerb/GB1) adds that league's most valuable players. Squad and league rows have no contract date or value history (those come from a player's own page); the "Maximum players from squads and tables" cap below applies to them.

## `topValue` (type: `boolean`):

Adds the first players of Transfermarkt's most-valuable table (25 per page, newest values). With monitoring on, a player who was not in that table on the last run is reported as a new entrant.

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

Caps the rows that come from club links, league links and the most-valuable table together (default 25, up to 500). Players you list yourself above are never capped.

## `includeHistory` (type: `boolean`):

Adds Transfermarkt's full market value history (date, value, club at the time) and, outside monitoring, the previous value and the change in percent, for every player you listed. One extra request per player, which roughly doubles the cost of a run; no extra charge. With monitoring on, the previous value comes from your last run, and a player seen for the first time gets Transfermarkt's previous value once without ticking this.

## `deltaMode` (type: `boolean`):

Turns the list into a watchlist. A player is reported when their market value moved by at least the percentage below since the last run, when their club changed, or (with the most-valuable table on) when they entered that table. The first run saves a baseline. Unchanged players are removed before you are billed, so a quiet run only costs the start fee. Schedule it daily or weekly, and have each alert posted to Discord, Slack or Telegram with "Send alerts to" below.

## `minChangePct` (type: `integer`):

Market values move in steps (for example €40m to €45m is +12.5%), so 5 skips nothing real. Use 0 to report every change.

## `deltaName` (type: `string`):

Leave empty and one is derived from your lists, so two schedules with different players keep separate memories. Type your own name to keep one memory when you add or remove players.

## `alertOnChangeOnly` (type: `boolean`):

On: a monitoring run returns (and bills) only value changes, club changes, new entrants and the first-run baseline. Off: every player comes back marked unchanged or changed, and all of them are billed.

## `skipFirstRun` (type: `boolean`):

The first run of a watchlist has nothing to compare with. Turn this on to remember every value without returning or billing it. Alerts start from the second run.

## `notifyUrl` (type: `string`):

Optional. After the players are billed, each value change, club change and new entrant is posted here as one message with a badge, the old and new value, club and link. Discord or Slack: paste the channel's webhook URL. Telegram: https://api.telegram.org/bot<token>/sendMessage?chat_id=<chat id>. Any other URL receives JSON. Messages are free, and a message that fails never fails the run (the rows' notifyErrors says why). Stored encrypted, never logged or written to the results.

## `notifyFormat` (type: `string`):

Leave on "Detect from the link": discord.com links get Discord messages, hooks.slack.com Slack, api.telegram.org Telegram, anything else JSON.

## `maxNotificationsPerRun` (type: `integer`):

Up to 100. Above this, one "+N more" message says how many more alerts are in the run's dataset. 0 sends only that summary message.

## `testRun` (type: `boolean`):

Turn this on to test your input on a small sample before running the full list. Turn it off to process everything.

## `onlyFound` (type: `boolean`):

Only keep rows where something was actually found. Misses are always free, whether or not you show them here.

## `includeKeywords` (type: `array`):

Optional. Only keep results that mention at least one of these words (e.g. a job title, a city, a product name). Leave empty to keep everything.

## `excludeKeywords` (type: `array`):

Optional. Drop any result that mentions one of these words. Leave empty to skip nothing.

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

Optional. Stop the run once this many results have been found — useful for a quick, cheap sample. Leave blank for no limit.

## `columns` (type: `array`):

Choose which pieces of information to include in each result row. All are included by default.

## `expandRows` (type: `boolean`):

When on, each player found gets its own row instead of being grouped under its player. You're still only charged once per player, no matter how many rows it produces.

## `maxConcurrency` (type: `integer`):

Parallel requests. Keep conservative — this target has no browser fallback, so getting blocked costs more than slow-and-steady.

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

Apify Proxy config. Residential recommended for anti-bot-sensitive targets.

## Actor input object example

```json
{
  "players": [
    "https://www.transfermarkt.com/lamine-yamal/profil/spieler/937958",
    "https://www.transfermarkt.com/erling-haaland/profil/spieler/418560",
    "https://www.transfermarkt.com/kylian-mbappe/profil/spieler/342229",
    "https://www.transfermarkt.com/michael-olise/profil/spieler/566723",
    "https://www.transfermarkt.com/jude-bellingham/profil/spieler/581678"
  ],
  "clubs": [],
  "topValue": false,
  "maxItems": 25,
  "includeHistory": false,
  "deltaMode": false,
  "minChangePct": 5,
  "deltaName": "",
  "alertOnChangeOnly": true,
  "skipFirstRun": false,
  "notifyFormat": "auto",
  "maxNotificationsPerRun": 20,
  "testRun": false,
  "onlyFound": false,
  "includeKeywords": [],
  "excludeKeywords": [],
  "columns": [
    "playerId",
    "name",
    "club",
    "position",
    "age",
    "nationality",
    "marketValueEur",
    "previousValueEur",
    "valueChangePct",
    "previousValueSource",
    "contractExpires",
    "changeType",
    "changeDetail",
    "valueHistory",
    "url",
    "checkedAt"
  ],
  "expandRows": true,
  "maxConcurrency": 1,
  "proxyConfiguration": {
    "useApifyProxy": true,
    "apifyProxyGroups": [
      "UNBLOCKER"
    ]
  }
}
```

# Actor output Schema

## `results` (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 = {
    "players": [
        "https://www.transfermarkt.com/lamine-yamal/profil/spieler/937958",
        "https://www.transfermarkt.com/erling-haaland/profil/spieler/418560",
        "https://www.transfermarkt.com/kylian-mbappe/profil/spieler/342229",
        "https://www.transfermarkt.com/michael-olise/profil/spieler/566723",
        "https://www.transfermarkt.com/jude-bellingham/profil/spieler/581678"
    ],
    "clubs": [],
    "includeKeywords": [],
    "excludeKeywords": []
};

// Run the Actor and wait for it to finish
const run = await client.actor("accountable_eel/transfermarkt-player-value-lookup").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 = {
    "players": [
        "https://www.transfermarkt.com/lamine-yamal/profil/spieler/937958",
        "https://www.transfermarkt.com/erling-haaland/profil/spieler/418560",
        "https://www.transfermarkt.com/kylian-mbappe/profil/spieler/342229",
        "https://www.transfermarkt.com/michael-olise/profil/spieler/566723",
        "https://www.transfermarkt.com/jude-bellingham/profil/spieler/581678",
    ],
    "clubs": [],
    "includeKeywords": [],
    "excludeKeywords": [],
}

# Run the Actor and wait for it to finish
run = client.actor("accountable_eel/transfermarkt-player-value-lookup").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 '{
  "players": [
    "https://www.transfermarkt.com/lamine-yamal/profil/spieler/937958",
    "https://www.transfermarkt.com/erling-haaland/profil/spieler/418560",
    "https://www.transfermarkt.com/kylian-mbappe/profil/spieler/342229",
    "https://www.transfermarkt.com/michael-olise/profil/spieler/566723",
    "https://www.transfermarkt.com/jude-bellingham/profil/spieler/581678"
  ],
  "clubs": [],
  "includeKeywords": [],
  "excludeKeywords": []
}' |
apify call accountable_eel/transfermarkt-player-value-lookup --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,accountable_eel/transfermarkt-player-value-lookup"
        }
    }
}
```

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/2h0pLQh7dCpE1odyc/builds/01sreebrjvdggYUrG/openapi.json
