# Transfermarkt Scraper — Players, Clubs & Market Values (`haketa/transfermarkt-scraper`) Actor

Scrape Transfermarkt football data: player profiles, club squads, league rosters, contracts, positions, nationalities and current market values. Search players, enter club URLs or competition codes, browse top-value rankings, and optionally add complete market-value and transfer histories.

- **URL**: https://apify.com/haketa/transfermarkt-scraper.md
- **Developed by:** [Haketa](https://apify.com/haketa) (community)
- **Categories:** Lead generation, Automation
- **Stats:** 3 total users, 2 monthly users, 77.8% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $1.50 / 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/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

<h1 align="center">⚽ Transfermarkt Scraper — Players, Clubs & Market Values</h1>

<p align="center"><strong>Turn global football profiles, squads and valuations into clean structured data.</strong></p>

<p align="center">
  <img src="https://img.shields.io/badge/PLAYERS-ENRICHED-2563EB?style=for-the-badge" alt="Players">
  <img src="https://img.shields.io/badge/CLUBS-%26%20LEAGUES-16A34A?style=for-the-badge" alt="Clubs">
  <img src="https://img.shields.io/badge/MARKET%20VALUES-HISTORY-F59E0B?style=for-the-badge" alt="Values">
  <img src="https://img.shields.io/badge/EXPORT-JSON%20%7C%20CSV%20%7C%20EXCEL-7C3AED?style=for-the-badge" alt="Exports">
</p>

### ⚡ At a glance

| | Capability |
|---|---|
| 🏆 Rankings | Collect the world's most valuable players automatically |
| 👤 Players | Search by name or paste player URLs and IDs |
| 🏟️ Clubs | Export complete club squads with contracts and valuations |
| 🌍 Leagues | Use a competition code to collect every club and squad |
| 📈 Values | Current value, numeric EUR value, update date and optional history |
| 🔄 Transfers | Optional complete career transfer history |
| 🎯 Filters | Position, nationality, age and minimum market value |
| 📦 Delivery | JSON, CSV, Excel, XML, API and integrations |

> 💡 Press **Start** with the ready-made input to collect the top-valued football players. No URLs or player IDs are required.

### What does this Transfermarkt scraper do?

Transfermarkt Scraper converts public football data into analysis-ready player and club records.

Use it to collect:

- current player market values;
- numeric EUR valuations;
- global most-valuable-player rankings;
- player identity and biographical information;
- positions and preferred foot;
- current clubs and competitions;
- contract and joining dates;
- agents and international records;
- complete club squads;
- league-wide club and player datasets;
- historical market-value changes;
- peak market values;
- transfer histories and fees.

The Actor automatically removes duplicate player IDs when the same footballer appears through several searches, clubs or rankings.

### Five ways to collect data

| Input mode | Example | Result |
|---|---|---|
| 🏆 Rankings | Enable `scrapeRankings` | Top-valued players across football |
| 🔎 Name search | `Erling Haaland` | Matching player profiles |
| 👤 Player URL or ID | `418560` | One enriched player record |
| 🏟️ Club URL or ID | Liverpool or `31` | Club summary and full squad |
| 🌍 Competition code | `GB1` | Every club and player in the league |

You can combine these modes in one run. Results are deduplicated automatically.

### Why this Actor?

Many football scrapers require users to locate every player URL manually. This Actor can start from rankings, player names, club IDs or league codes.

It is designed for both quick exports and deeper research:

- fast listing mode avoids unnecessary profile requests;
- enriched mode adds profile and contract data;
- history options are independent;
- clear `recordType` values distinguish players and clubs;
- market-value text is preserved alongside numeric EUR values;
- every record contains its source URL and scrape timestamp;
- missing optional data stays empty instead of being fabricated.

### 🎯 Use cases

| Use case | How the data helps |
|---|---|
| 🔭 Player scouting | Filter young players by position, nationality and valuation |
| 💼 Recruitment analysis | Review contracts, clubs, agents and career movement |
| 📊 Football analytics | Build valuation and squad-composition datasets |
| 📈 Value monitoring | Schedule runs and compare player values over time |
| 📰 Sports media | Power rankings, club profiles and transfer content |
| 🎮 Fantasy football | Add positions, clubs and player values to models |
| 🏟️ Club benchmarking | Compare squad size, age and total market value |
| 🌍 League research | Export every player from a competition with one code |
| 💰 Transfer research | Analyze fees, player values and movement history |
| 🤖 AI workflows | Feed structured football records into search and RAG systems |

#### Scouts and recruitment teams

Find players who match a position, maximum age, nationality and minimum valuation. Enriched profiles add contract dates, preferred foot, agent and international data.

#### Analysts and researchers

Collect repeatable snapshots with numeric market values. Historical valuation arrays support development curves, peak-value analysis and longitudinal research.

#### Sports publishers

Generate player and club datasets for rankings, comparison pages, transfer stories and automated matchday content.

#### Clubs and agencies

Compare squads and identify contract timelines, player representation and market positioning across leagues.

### 🚀 Quick start

1. Open the Actor input page.
2. Keep **Scrape most valuable players** enabled or choose another input method.
3. Choose whether player profiles should be enriched.
4. Enable value or transfer history only when needed.
5. Set the maximum number of results.
6. Click **Start**.
7. Download the dataset as JSON, CSV or Excel.

### Input reference

| Field | Type | Default | Description |
|---|---|---:|---|
| `scrapeRankings` | Boolean | `true` | Browse most-valuable-player rankings |
| `playerQueries` | String list | Empty | Player names to search |
| `playerUrls` | String list | Empty | Direct player URLs or numeric IDs |
| `clubUrls` | String list | Empty | Club URLs or numeric IDs |
| `competitionCodes` | String list | Empty | League and competition codes |
| `season` | Integer | `2026` | Start year of the season |
| `includePlayerDetails` | Boolean | `true` | Full profile enrichment |
| `includeMarketValueHistory` | Boolean | `false` | Dated value history and peak value |
| `includeTransferHistory` | Boolean | `false` | Career transfers and fees |
| `includeClubRecords` | Boolean | `true` | Add club summary rows |
| `positions` | String list | Empty | Position filters |
| `nationalities` | String list | Empty | Citizenship filters |
| `maxAge` | Integer | `0` | Maximum age; zero disables |
| `minMarketValueEur` | Integer | `0` | Minimum current value in EUR |
| `maxItems` | Integer | `1000` | Maximum total records |
| `maxConcurrency` | Integer | `6` | Parallel enrichment requests |
| `proxyConfiguration` | Object | Direct | Optional Apify Proxy settings |

### Competition codes

Common examples:

| Competition | Code |
|---|---|
| Premier League | `GB1` |
| LaLiga | `ES1` |
| Serie A | `IT1` |
| Bundesliga | `L1` |
| Ligue 1 | `FR1` |
| Süper Lig | `TR1` |
| Liga Portugal | `PO1` |
| Eredivisie | `NL1` |
| Major League Soccer | `MLS1` |
| Saudi Pro League | `SA1` |

Competition availability and codes can change. Direct competition URLs are not required when the code is known.

### Input examples

#### Most valuable players

```json
{
  "scrapeRankings": true,
  "maxItems": 200,
  "includePlayerDetails": true
}
```

#### Search several players

```json
{
  "scrapeRankings": false,
  "playerQueries": ["Erling Haaland", "Lamine Yamal", "Kylian Mbappe"],
  "includePlayerDetails": true,
  "includeMarketValueHistory": true,
  "maxItems": 20
}
```

#### One player by ID

```json
{
  "scrapeRankings": false,
  "playerUrls": ["418560"],
  "includePlayerDetails": true,
  "includeMarketValueHistory": true,
  "includeTransferHistory": true
}
```

#### Complete club squad

```json
{
  "scrapeRankings": false,
  "clubUrls": ["31"],
  "season": 2026,
  "includeClubRecords": true,
  "includePlayerDetails": true,
  "maxItems": 100
}
```

#### Whole league

```json
{
  "scrapeRankings": false,
  "competitionCodes": ["GB1"],
  "season": 2026,
  "includeClubRecords": true,
  "includePlayerDetails": false,
  "maxItems": 1000
}
```

#### Young high-value forwards

```json
{
  "scrapeRankings": true,
  "positions": ["Forward", "Winger"],
  "maxAge": 23,
  "minMarketValueEur": 20000000,
  "maxItems": 500
}
```

> 💡 Filters are applied to the final player data. Set `maxItems` high enough when using narrow filters so the Actor has enough candidates to evaluate.

### Output: player records

#### 👤 Identity

| Field | Meaning | Coverage |
|---|---|---|
| `recordType` | Always `player` | 🟢 Every player |
| `playerId` | Stable Transfermarkt player ID | 🟢 Every player |
| `name` | Display name | 🟢 Every player |
| `fullName` | Full home-country name | 🟡 When published |
| `dateOfBirth` | Date of birth | 🟢 Enriched profiles |
| `age` | Current listed age | 🟢 Nearly every player |
| `placeOfBirth` | Birthplace | 🟡 When published |
| `nationalities` | Citizenship list | 🟢 Nearly every player |
| `imageUrl` | Player portrait | 🟢 Nearly every player |
| `url` | Canonical profile URL | 🟢 Every player |

#### ⚽ Sporting profile

| Field | Meaning | Coverage |
|---|---|---|
| `position` | Detailed playing position | 🟢 Nearly every player |
| `preferredFoot` | Left, right or both | 🟢 Enriched active players |
| `height` | Listed player height | 🟢 Enriched profiles |
| `shirtNumber` | Current squad number | 🟡 When assigned |
| `currentClub` | Current club | 🟢 Active players |
| `currentClubId` | Stable club ID | 🟢 Active players |
| `competition` | Current league or competition | 🟡 Enriched profiles |

#### 📄 Contract and representation

| Field | Meaning | Coverage |
|---|---|---|
| `joinedDate` | Date joined current club | 🟡 When published |
| `contractExpiry` | Current contract end | 🟡 When published |
| `agent` | Player representative | 🟡 When published |
| `currentNationalTeam` | National team | 🟡 International players |
| `nationalTeamCaps` | International appearances | 🟡 International players |
| `nationalTeamGoals` | International goals | 🟡 International players |

#### 💶 Market value

| Field | Meaning | Coverage |
|---|---|---|
| `marketValue` | Display value such as `€80.00m` | 🟢 Ranked players |
| `marketValueEur` | Numeric EUR value | 🟢 When value exists |
| `marketValueUpdatedAt` | Latest update date | 🟢 Enriched profiles |
| `marketValueHistory` | Dated historical valuations | ⚪ Optional |
| `peakMarketValue` | Highest historical display value | ⚪ History mode |
| `peakMarketValueEur` | Highest historical numeric value | ⚪ History mode |
| `peakMarketValueDate` | Date of highest value | ⚪ History mode |

#### 🔄 Transfer history

Each optional transfer entry can contain:

- season;
- transfer date;
- previous club and club ID;
- new club and club ID;
- market value at the time;
- transfer fee;
- numeric fee in EUR;
- source URL.

### Output: club records

| Field | Meaning |
|---|---|
| `recordType` | Always `club` |
| `clubId` | Stable club identifier |
| `name` | Club name |
| `competitionCode` | Competition code |
| `competition` | Competition name |
| `season` | Requested season |
| `squadSize` | Number of squad players |
| `averageAge` | Average squad age |
| `averageMarketValue` | Display average value |
| `averageMarketValueEur` | Numeric average value |
| `totalMarketValue` | Display squad value |
| `totalMarketValueEur` | Numeric squad value |
| `logoUrl` | Club badge |
| `url` | Club profile URL |
| `squadUrl` | Squad source URL |

### Example player result

```json
{
  "recordType": "player",
  "playerId": "418560",
  "name": "Erling Haaland",
  "fullName": "Erling Braut Håland",
  "age": 26,
  "nationalities": ["Norway"],
  "height": "1,95 m",
  "position": "Attack - Centre-Forward",
  "preferredFoot": "left",
  "currentClub": "Man City",
  "currentClubId": "281",
  "competition": "Premier League",
  "shirtNumber": 9,
  "marketValue": "€220.00m",
  "marketValueEur": 220000000,
  "marketValueUpdatedAt": "22/07/2026",
  "detailEnriched": true
}
```

### Data quality

The Actor follows practical quality rules:

- player records are deduplicated by player ID;
- club records are deduplicated by club ID;
- numeric valuations are stored with original display values;
- missing values are not guessed;
- detail failures fall back to usable listing records;
- every result includes a collection timestamp;
- source URLs remain available for verification;
- optional high-cost requests stay disabled unless selected.

### Performance tips

#### Fastest collection

- keep `includePlayerDetails` disabled;
- keep history options disabled;
- collect squads or rankings;
- use a focused result limit.

#### Richest records

- enable player details;
- enable value history for trend research;
- enable transfers only when career movement is required;
- keep concurrency between four and eight.

#### Large league export

- enter one competition code;
- disable player details for the first run;
- set `maxItems` above the expected squad count;
- enrich selected players in a second run if needed.

### Integrations

Send Transfermarkt data to:

- Google Sheets;
- Airtable;
- Make;
- Zapier;
- Slack;
- webhooks;
- REST API clients;
- Python and JavaScript applications;
- BI dashboards;
- databases and warehouses;
- scouting and recruitment systems;
- AI agents and RAG pipelines.

### Scheduling

Schedule weekly or monthly runs to monitor:

- player valuation changes;
- contract timelines;
- squad composition;
- club total values;
- high-value young players;
- transfer activity;
- league-level changes.

### Honest limitations

- Market values are estimates, not guaranteed transfer fees.
- Profile completeness differs by player and competition.
- Retired or lower-league players may have fewer fields.
- Competition codes and seasonal squad availability can change.
- Very large enriched runs take longer than overview exports.
- Transfermarkt may temporarily limit high request volumes.
- The Actor collects public information and does not require an account.

### FAQ

#### Do I need a Transfermarkt account?

No. The Actor uses publicly visible football data.

#### Can I start without URLs?

Yes. Rankings are enabled by default, and player-name search is supported.

#### Can I scrape a whole club?

Yes. Enter a club URL or numeric club ID.

#### Can I scrape a whole league?

Yes. Enter a competition code such as `GB1` or `ES1`.

#### Can I combine clubs and player searches?

Yes. All supported input modes can run together.

#### Are duplicate players removed?

Yes. Stable player IDs are used for deduplication.

#### Does the Actor return numeric market values?

Yes. `marketValueEur` is suitable for sorting and calculations.

#### Is value history included automatically?

No. Enable it when needed to keep ordinary runs fast and inexpensive.

#### Can I get the player's peak market value?

Yes. It is calculated when market-value history is enabled.

#### Can I collect transfer fees?

Yes. Enable transfer history.

#### Can I filter by age?

Yes. Set `maxAge`.

#### Can I filter by position?

Yes. Position matching is case-insensitive and supports partial names.

#### Can I filter by nationality?

Yes. Enter English citizenship names in `nationalities`.

#### Can I export to Excel?

Yes. Apify datasets support Excel, CSV, JSON, XML and other formats.

#### Can it run automatically?

Yes. Use Apify Schedules and webhooks.

#### Why are some contract or agent values empty?

Those fields are returned only when publicly listed for the player.

#### Should I enable a proxy?

Start with direct mode. Enable Apify Proxy if the source limits your run.

### Responsible use

Use the Actor and its output responsibly. Comply with applicable laws, contractual requirements, privacy rules and the source website's terms. Do not use data for unlawful surveillance, harassment, spam or prohibited automated decisions.

Transfermarkt is a trademark of its respective owner. This Actor is independent and is not affiliated with, sponsored by or endorsed by Transfermarkt.

### Support

When reporting a problem, include the run ID, sanitized input and an example public URL. Never share API tokens, passwords, cookies or private credentials.

***

<p align="center"><strong>Discover players. Compare clubs. Track football market value.</strong></p>

# Actor input Schema

## `scrapeRankings` (type: `boolean`):

Collect the global most-valuable-player ranking. This is the easiest way to get a large dataset without entering URLs.

## `playerQueries` (type: `array`):

Search one or more players by name. The best matching player results are added to the dataset.

## `playerUrls` (type: `array`):

Transfermarkt player profile URLs or numeric player IDs.

## `clubUrls` (type: `array`):

Transfermarkt club URLs or numeric club IDs. Every squad player becomes a result.

## `competitionCodes` (type: `array`):

Collect every club and squad in a league. Examples: GB1, ES1, IT1, L1, FR1, TR1, MLS1, SA1.

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

For the 2026/27 season enter 2026. Applies to club and competition squad collection.

## `includePlayerDetails` (type: `boolean`):

Add full name, birthplace, height, foot, agent, contract, international record and precise value-update date.

## `includeMarketValueHistory` (type: `boolean`):

Add every dated historical valuation plus peak value and peak date. Requires player enrichment.

## `includeTransferHistory` (type: `boolean`):

Add career transfers with previous club, new club, date, fee and market value. Requires player enrichment.

## `includeClubRecords` (type: `boolean`):

When collecting clubs or competitions, also return a club record with squad size, average age and total market value.

## `positions` (type: `array`):

Keep matching positions only. Partial matching works, e.g. Goalkeeper, Centre-Back, Midfield, Winger, Centre-Forward.

## `nationalities` (type: `array`):

Keep players with one of these citizenships. Use English country names such as France, Türkiye or Brazil.

## `maxAge` (type: `integer`):

Use 0 for no age limit.

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

Keep players whose current market value reaches this amount. Use 0 to disable.

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

Maximum player and club records saved. Increase this to collect more sellable data in one run.

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

Recommended: 4–8. Transfermarkt may limit aggressive traffic.

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

Residential proxies are required (Transfermarkt uses an AWS WAF challenge).

## Actor input object example

```json
{
  "scrapeRankings": true,
  "playerQueries": [
    "Erling Haaland",
    "Lamine Yamal"
  ],
  "playerUrls": [
    "https://www.transfermarkt.com/erling-haaland/profil/spieler/418560",
    "342229"
  ],
  "clubUrls": [
    "https://www.transfermarkt.com/fc-liverpool/startseite/verein/31",
    "281"
  ],
  "competitionCodes": [
    "GB1",
    "ES1"
  ],
  "season": 2026,
  "includePlayerDetails": true,
  "includeMarketValueHistory": false,
  "includeTransferHistory": false,
  "includeClubRecords": true,
  "positions": [],
  "nationalities": [],
  "maxAge": 0,
  "minMarketValueEur": 0,
  "maxItems": 50,
  "maxConcurrency": 6,
  "proxyConfiguration": {
    "useApifyProxy": true
  }
}
```

# Actor output Schema

## `dataset` (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 = {
    "scrapeRankings": true,
    "playerQueries": [],
    "playerUrls": [],
    "clubUrls": [],
    "competitionCodes": [],
    "includePlayerDetails": false,
    "includeMarketValueHistory": false,
    "includeTransferHistory": false,
    "positions": [],
    "nationalities": [],
    "maxItems": 50,
    "proxyConfiguration": {
        "useApifyProxy": true
    }
};

// Run the Actor and wait for it to finish
const run = await client.actor("haketa/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 = {
    "scrapeRankings": True,
    "playerQueries": [],
    "playerUrls": [],
    "clubUrls": [],
    "competitionCodes": [],
    "includePlayerDetails": False,
    "includeMarketValueHistory": False,
    "includeTransferHistory": False,
    "positions": [],
    "nationalities": [],
    "maxItems": 50,
    "proxyConfiguration": { "useApifyProxy": True },
}

# Run the Actor and wait for it to finish
run = client.actor("haketa/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 '{
  "scrapeRankings": true,
  "playerQueries": [],
  "playerUrls": [],
  "clubUrls": [],
  "competitionCodes": [],
  "includePlayerDetails": false,
  "includeMarketValueHistory": false,
  "includeTransferHistory": false,
  "positions": [],
  "nationalities": [],
  "maxItems": 50,
  "proxyConfiguration": {
    "useApifyProxy": true
  }
}' |
apify call haketa/transfermarkt-scraper --silent --output-dataset

```

## MCP server setup

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