# Transfermarkt Scraper - Market Values, Squads and Transfers (`kamerozkan/transfermarkt-scraper`) Actor

Transfermarkt scraper for league and club squads: player market values in EUR, position, age, nationality, height, foot, contract end, joined date, signed from and transfer fee. Monitor mode flags market value changes, new signings and departures between runs. Plain HTTP, no login.

- **URL**: https://apify.com/kamerozkan/transfermarkt-scraper.md
- **Developed by:** [Kamer Ozkan](https://apify.com/kamerozkan) (community)
- **Categories:** Automation
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $1.20 / 1,000 players

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 Scraper - Market Values, Squads and Transfers

Transfermarkt scraper for player market values, squads, contracts and transfer fees: give it a league code (GB1, L1, ES1, IT1, FR1 and any other Transfermarkt competition) or club URLs and get one clean row per player. Schedule it to monitor market value changes, new signings and departures between runs.

### What does Transfermarkt Scraper do?

It reads the public Transfermarkt league and detailed squad pages and returns one row per player: name, position, shirt number, date of birth and age, nationalities, height, preferred foot, the date the player joined the club, the previous club with the transfer fee, contract end, market value as shown and in euros, photo and profile link, plus club, league and season.

- **Leagues**: every club of a league (or the top N clubs by market value) in one run. Works for any Transfermarkt competition code: Premier League GB1, Championship GB2, Bundesliga L1, LaLiga ES1, Serie A IT1, Ligue 1 FR1, Eredivisie NL1, Liga Portugal PO1, Super Lig TR1, MLS MLS1 and more. League names such as "serie a" work too.
- **Clubs**: any club URL or numeric club id, also outside the big leagues.
- **Seasons**: the current season by default, or any past season by start year (2025 for 25/26).
- **Transfers**: `joinedThisSeason`, `joinedDate`, `signedFrom` and `transferFee` show the summer and winter signings of every squad.
- **Market value and transfer monitor**: with **Track market value changes** on (the default) the actor remembers every squad. Schedule the same input and each row tells you the previous market value and the change in euros, `isNewInSquad` marks new arrivals, and the OUTPUT record lists departed players. Turn on **Only changed players** to pay only for changes.

No login, no Transfermarkt account and no API key are needed. Proxy is included in the price.

### Who is it for?

- **Football scouts and agents** screening squads by age, position, contract end and market value.
- **Fantasy football, betting and sports data analysts** who need market values and squads as structured data per league.
- **Clubs and journalists** following transfer windows: new signings, fees and departures per club.
- **Data teams and app builders** who want a Transfermarkt API alternative for market values and transfers.

### What data can you get?

| Field | Example |
|---|---|
| `name`, `playerId`, `url` | Erling Haaland, 418560, Transfermarkt profile link |
| `position`, `shirtNumber` | Centre-Forward, 9 |
| `dateOfBirth`, `age` | 2000-07-21, 26 |
| `nationalities` | \["Norway"] |
| `heightM`, `foot` | 1.95, left |
| `clubName`, `clubId`, `league`, `leagueCode` | Manchester City, 281, Premier League, GB1 |
| `season`, `seasonLabel` | 2026, 26/27 |
| `marketValue`, `marketValueEur` | €220.00m, 220000000 |
| `contractUntil` | 2034-06-30 |
| `joinedDate`, `joinedThisSeason` | 2022-07-01, false |
| `signedFrom`, `signedFromClubId`, `transferFee` | Borussia Dortmund, 16, €60.00m (or free transfer, loan) |
| `previousMarketValueEur`, `marketValueChangeEur`, `isNewInSquad` | Filled from the second run of the same club |
| `imageUrl` | Player photo |
| `checkedAt` | 2026-10-18T08:24:21+00:00 |

### How much does it cost?

You pay only for player rows: **$1.50 per 1,000 players** on the Free plan, with lower prices on paid Apify plans. League pages, club pages and the proxy are not charged extra.

Worked examples:

- One full Premier League squad list (20 clubs, about 550 players) costs about **$0.83**.
- A scout who monitors the top 5 European leagues (about 2,700 players) once a week reads about 10,800 rows a month, about **$16.20 per month**. With **Only changed players** on, unchanged players are skipped and not charged.

Set "Max players" or a maximum cost per run to cap spending.

### How to use it

1. Click **Try for free**.
2. Add one or more **Leagues** (for example GB1 or L1) and/or **Clubs** (club URLs or ids).
3. Optional: set **Max clubs per league**, a **Season** start year and a **Min market value (EUR)**.
4. Click **Start**, then download the results as JSON, CSV or Excel, or read them with the API.
5. To monitor market values and transfers, save the input as a task and add a schedule (for example weekly, or daily during a transfer window).

### Input example

```json
{
  "leagues": ["L1"],
  "maxClubsPerLeague": 3,
  "season": 2026,
  "minMarketValueEur": 5000000,
  "maxPlayers": 120,
  "trackChanges": true
}
```

### Output example

Real row from a run on 2026-10-18 (Premier League, current season):

```json
{
  "playerId": "229604",
  "name": "Gerónimo Rulli",
  "position": "Goalkeeper",
  "shirtNumber": 28,
  "dateOfBirth": "1992-05-20",
  "age": 34,
  "nationalities": ["Argentina", "Italy"],
  "heightM": 1.89,
  "foot": "right",
  "joinedDate": "2026-08-12",
  "signedFrom": "Olympique Marseille",
  "signedFromClubId": "244",
  "transferFee": "€3.50m",
  "joinedThisSeason": true,
  "contractUntil": "2028-06-30",
  "marketValue": "€5.00m",
  "marketValueEur": 5000000,
  "imageUrl": "https://img.a.transfermarkt.technology/portrait/medium/229604-1698670758.jpg",
  "url": "https://www.transfermarkt.com/geronimo-rulli/profil/spieler/229604",
  "clubId": "281",
  "clubName": "Manchester City",
  "league": "Premier League",
  "leagueCode": "GB1",
  "season": 2026,
  "seasonLabel": "26/27",
  "previousMarketValueEur": null,
  "marketValueChangeEur": null,
  "isNewInSquad": false,
  "checkedAt": "2026-10-18T08:24:21+00:00"
}
```

The OUTPUT record of the run shows the number of players and clubs read, the departed players since the last run (`departures`, not charged) and any page that could not be loaded.

### Integrations and API

Run it from your code with the Apify API or the `apify-client` package, schedule it in Apify, or connect it to Make, n8n, Zapier, Google Sheets or a webhook (for example a Slack message when `marketValueChangeEur` is above 5,000,000 or `isNewInSquad` is true).

```python
from apify_client import ApifyClient

client = ApifyClient("<YOUR_APIFY_TOKEN>")
run = client.actor("kamerozkan/transfermarkt-scraper").call(run_input={
    "leagues": ["GB1", "ES1"],
    "minMarketValueEur": 20000000,
    "maxPlayers": 500,
})
for item in client.dataset(run["defaultDatasetId"]).iterate_items():
    print(item["name"], item["clubName"], item["marketValueEur"], item["contractUntil"])
```

### FAQ

**Which league codes can I use?** Every Transfermarkt competition code: it is the part after `/wettbewerb/` in a league URL, for example GB1 in `transfermarkt.com/premier-league/startseite/wettbewerb/GB1`. You can also paste the league URL itself.

**Can I get a past season?** Yes. Set **Season** to the start year: 2025 for 25/26, 2024 for 24/25. Squads, clubs and market values are then those of that season.

**How do I track transfers?** Each row shows when the player joined, from which club and for which fee. `joinedThisSeason` marks this season's arrivals. With change tracking on, a scheduled run also marks new arrivals since your last run and lists departures in the OUTPUT record.

**How does it know the previous market value?** It stores the last squad of each club and season in a key-value store in your own Apify account. Different seasons keep separate histories.

**Why is `transferFee` empty for some players?** Youth players promoted from the club's own academy and some free agents have no fee on Transfermarkt.

**Can I look up single players by profile URL?** Not yet: this version reads squads. Open an issue if you need player profiles, market value history or league transfer lists and it will be added.

**Is it legal to collect this data?** It collects public football data that Transfermarkt shows to every visitor: professional players as public sports figures, their clubs, contracts and market values. No logins and no private persons' data. You are responsible for how you use it.

### Support and feedback

- Found a bug or missing a field? Open an issue on the **Issues** tab of this Actor with your run link. We reply within
  48 hours and ship most fixes within a few days.
- Have an idea for a feature? Issues are the fastest way to get it built.
- If the Actor saves you time, a short review on this page helps other users find it.

# Actor input Schema

## `leagues` (type: `array`):

Transfermarkt competition codes or league URLs. Every club of the league is read (see Max clubs per league). Examples: GB1 (Premier League), L1 (Bundesliga), ES1 (LaLiga), IT1 (Serie A), FR1 (Ligue 1), NL1, PO1, TR1, GB2, or https://www.transfermarkt.com/premier-league/startseite/wettbewerb/GB1

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

Club URLs or numeric Transfermarkt club ids, for example https://www.transfermarkt.com/fc-bayern-munchen/kader/verein/27 or 27. Read in addition to the leagues.

## `season` (type: `integer`):

Season start year, for example 2026 for 26/27 or 2025 for 25/26. Leave empty for the current season.

## `maxPlayers` (type: `integer`):

Stop after this many player rows. You are charged per player row, so this also caps the cost of the run. A full Premier League season is about 550 players.

## `maxClubsPerLeague` (type: `integer`):

Read only the first N clubs of each league (ordered by total market value). 0 means all clubs.

## `minMarketValueEur` (type: `integer`):

Only keep players with at least this market value in euros, for example 10000000 for 10 million. Players below it are not charged.

## `trackChanges` (type: `boolean`):

Remember market values per club between runs and add previousMarketValueEur, marketValueChangeEur and isNewInSquad to each row. Departed players are listed in the OUTPUT record. Schedule the actor to get a transfer and market value monitor.

## `onlyChanges` (type: `boolean`):

On repeat runs, output (and charge) only players whose market value changed or who are new in the squad.

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

Apify Proxy. By default the run uses residential proxy (Transfermarkt blocks most datacenter IPs); choose proxy groups here to override.

## Actor input object example

```json
{
  "leagues": [
    "GB1"
  ],
  "maxPlayers": 100,
  "maxClubsPerLeague": 0,
  "trackChanges": true,
  "onlyChanges": false,
  "proxyConfiguration": {
    "useApifyProxy": true
  }
}
```

# Actor output Schema

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

One row per result in the default dataset.

# 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 = {
    "leagues": [
        "GB1"
    ],
    "maxPlayers": 100,
    "proxyConfiguration": {
        "useApifyProxy": true
    }
};

// Run the Actor and wait for it to finish
const run = await client.actor("kamerozkan/transfermarkt-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 = {
    "leagues": ["GB1"],
    "maxPlayers": 100,
    "proxyConfiguration": { "useApifyProxy": True },
}

# Run the Actor and wait for it to finish
run = client.actor("kamerozkan/transfermarkt-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 '{
  "leagues": [
    "GB1"
  ],
  "maxPlayers": 100,
  "proxyConfiguration": {
    "useApifyProxy": true
  }
}' |
apify call kamerozkan/transfermarkt-scraper --silent --output-dataset

```

## MCP server setup

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