# SofaScore Tennis Rankings Scraper (ATP, WTA, UTR) (`automation-lab/sofascore-tennis-atp-wta-utr-ranking-lists`) Actor

Export current ATP, WTA, live ATP/WTA and UTR men/women tennis rankings from SofaScore: rank, points, movement, best rank, country and player IDs for every listed player.

- **URL**: https://apify.com/automation-lab/sofascore-tennis-atp-wta-utr-ranking-lists.md
- **Developed by:** [Automation Lab](https://apify.com/automation-lab) (community)
- **Categories:** Sports
- **Security:** Limited permissions
- **Stats:** 3 total users, 2 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $0.55 / 1,000 ranking rows

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

## SofaScore Tennis Rankings Scraper (ATP, WTA, UTR)

Export the current **ATP, WTA, live ATP, live WTA, UTR men and UTR women tennis rankings** from SofaScore. Pick one or several ranking lists and get one clean row per player, in SofaScore's order from No. 1 down: rank, points, rank and points movement, career-best rank, nationality, SofaScore player ID and a link to the player page.

Each list holds up to 500 players and the whole list is fetched in one request, so even a full export of all six lists finishes in seconds. No login, cookies or proxy setup is needed.

### What does the SofaScore tennis rankings scraper do?

- Exports any combination of six SofaScore tennis ranking lists in one run:
  - **ATP singles** (official weekly ranking)
  - **ATP live** (includes points from tournaments in progress)
  - **WTA singles** (official weekly ranking)
  - **WTA live**
  - **UTR men** and **UTR women** (Universal Tennis Rating; points are the rating, e.g. 16.45)
- Keeps SofaScore's order and the published rank, including shared ranks.
- Calculates `rankChange` and `pointsChange` from the previous ranking for you.
- Adds live-ranking extras (points after the next win, maximum possible points) and the UTR best-rank date.
- Optionally keeps only players of selected nationalities, e.g. every Spanish and American player in the top 500.

### Who is it for?

- **Betting and fantasy analysts** who join live rankings to match data and need fresh points and movement every day.
- **Tennis journalists and bloggers** who publish weekly "biggest movers" tables or national rankings (e.g. all British players in the WTA top 500).
- **Federations, academies and agents** tracking their players' ATP, WTA and UTR positions over time.
- **Data engineers and researchers** who load ranking snapshots into a warehouse or spreadsheet on a schedule.
- **App and widget builders** who need a simple JSON feed of the current top 10, 50 or 500.

### Why use this Actor?

- **All six lists in one run.** ATP, WTA, both live rankings and both UTR lists, without switching modes or running the Actor six times.
- **Movement already calculated.** `rankChange` (positive = moved up) and `pointsChange` are ready for charts and alerts.
- **Join-ready IDs.** `playerId` is SofaScore's player ID, the same ID our other SofaScore tennis Actors return, and `playerUrl` links to the player page.
- **Fast and light.** One request per list, no browser, no residential proxy, 256 MB memory.
- **Honest failures.** If SofaScore cannot be reached, the run fails with a clear message instead of returning an empty "success".

### What data can I extract?

| Field | Meaning |
| --- | --- |
| `ranking`, `rankingName`, `rankingTypeId` | Which list the row belongs to (`atp`, `atpLive`, `wta`, `wtaLive`, `utrMen`, `utrWomen`) |
| `position` | 1-based position in SofaScore's order |
| `rank` | Published rank (players can share a rank) |
| `playerId`, `playerName`, `shortName`, `playerSlug`, `nameCode` | Player identity on SofaScore |
| `gender` | `M` or `F` |
| `countryName`, `countryAlpha2`, `countryAlpha3` | Nationality |
| `points` | Ranking points; for UTR lists the UTR rating |
| `previousRank`, `rankChange` | Previous rank and places moved (positive = up). In live lists `previousRank` is the current official rank |
| `previousPoints`, `pointsChange` | Points at the previous update and the change (ATP and UTR lists) |
| `bestRank`, `bestRankDate` | Career-high rank as published; date only for UTR lists |
| `tournamentsPlayed` | Tournaments counted (ATP list) |
| `nextWinPoints`, `maxPoints` | Live lists only, for players still in a tournament: points after the next win, and if they win the event |
| `sofascoreFollowers` | How many SofaScore users follow the player |
| `playerUrl` | SofaScore player page |
| `rankingUpdatedAt`, `scrapedAt` | When SofaScore updated the list and when the row was exported |

Fields SofaScore does not publish for a list are `null` (for example `tournamentsPlayed` on the WTA list or `nextWinPoints` on official lists).

### How much does it cost to scrape ATP, WTA and UTR tennis rankings?

This Actor uses pay-per-event pricing: a small fixed fee per run plus a fee per ranking row saved.

| Event | Price (Free plan) |
| --- | --- |
| Run start (once per run) | $0.001 |
| Ranking row saved | $0.0010626 |

Paid Apify plans get lower per-row prices: Bronze $0.000924, Silver $0.00072072, Gold and above $0.0005544. The start fee is $0.001 on every plan.

Examples on the Free plan:

- ATP top 10: $0.001 + 10 × $0.0010626 = **about $0.012**
- ATP and WTA top 100 (200 rows): $0.001 + 200 × $0.0010626 = **about $0.21**
- All six lists, complete (3,000 rows): $0.001 + 3,000 × $0.0010626 = **about $3.19**

Apify's free monthly credit covers many small ranking exports. You only pay for rows actually saved; you can cap spending with the run's maximum charge setting, and the Actor stops cleanly at that budget.

### How to scrape SofaScore tennis rankings

1. Open the Actor's **Input** tab.
2. Under **Ranking lists**, keep ATP and WTA or pick any of the six lists.
3. Set **Max players per ranking list** (20 for a quick test, 500 for complete lists).
4. Optionally enter nationality codes such as `ES`, `USA` or `GBR` to keep only those players.
5. Click **Start** and open the **Output** tab.
6. Download JSON, CSV or Excel, or read the dataset through the API.

### Input parameters

| Input | Default | Behavior |
| --- | --- | --- |
| `rankings` | `["atp", "wta"]` | Lists to export: `atp`, `atpLive`, `wta`, `wtaLive`, `utrMen`, `utrWomen`. Duplicates are ignored. |
| `maxItemsPerRanking` | `100` | Players saved per list (1–1000), counted after the country filter, in source order. SofaScore publishes up to 500 players per list. |
| `countryCodes` | empty | Keep only players whose nationality matches one of these ISO codes (2 or 3 letters, exact, case-insensitive). Ranks stay world ranks. |

Example input:

```json
{
  "rankings": ["atp", "atpLive", "utrMen"],
  "maxItemsPerRanking": 50,
  "countryCodes": ["ES", "USA"]
}
```

### Output example

A real row from the ATP list (3 November 2026):

```json
{
  "ranking": "atp",
  "rankingName": "ATP singles rankings",
  "rankingTypeId": 5,
  "position": 1,
  "rank": 1,
  "playerId": 57163,
  "playerName": "Alexander Zverev",
  "shortName": "A. Zverev",
  "playerSlug": "zverev-alexander",
  "nameCode": "ZVE",
  "gender": "M",
  "countryName": "Germany",
  "countryAlpha2": "DE",
  "countryAlpha3": "DEU",
  "points": 9550,
  "previousRank": 2,
  "rankChange": 1,
  "previousPoints": 9750,
  "pointsChange": -200,
  "bestRank": 2,
  "bestRankDate": null,
  "tournamentsPlayed": 25,
  "nextWinPoints": null,
  "maxPoints": null,
  "sofascoreFollowers": 90568,
  "playerUrl": "https://www.sofascore.com/tennis/player/zverev-alexander/57163",
  "rankingUpdatedAt": "2026-11-03T06:00:51.000Z",
  "scrapedAt": "2026-11-03T07:08:06.701Z"
}
```

Values are copied as SofaScore publishes them; for example `bestRank` can lag behind a brand-new No. 1 until SofaScore updates it.

The run also saves an `OUTPUT` summary in the key-value store with, for each list, the rows available, rows matching your filter, rows saved and the list's update time.

### Tips and limits

- **Complete lists:** set `maxItemsPerRanking` to 500 or more. SofaScore currently publishes 500 players per list; a few more rank numbers appear when players share a rank.
- **Country filter first, then limit:** with `countryCodes: ["GB"]` and a limit of 20 you get the 20 best-ranked British players, with their world ranks.
- **Live rankings** move during tournaments; schedule runs as often as you need. Official ATP and WTA lists update weekly, UTR lists more often.
- **No match data:** this Actor exports ranking lists only, not matches, draws, doubles rankings or player career statistics.
- **Failures are visible:** if one selected list cannot be fetched, the other lists are still saved and the run then fails with a message naming the list.

### Integrations

- **Google Sheets / Excel:** schedule a weekly run and export the dataset as CSV to keep a ranking history table.
- **Make, Zapier, n8n:** trigger on run success and post the top movers (`rankChange` ≥ 10) to Slack or a newsletter.
- **Data warehouse:** load rows keyed by `ranking`, `playerId` and `rankingUpdatedAt` to build ranking time series.
- **Webhooks:** call your own endpoint when a run finishes and fetch the dataset items.
- **Other SofaScore tennis Actors:** use `playerId` to join rankings to live scores or tournament results.

### API usage

Start a run and get results with cURL:

```bash
curl -X POST "https://api.apify.com/v2/acts/automation-lab~sofascore-tennis-atp-wta-utr-ranking-lists/run-sync-get-dataset-items?token=YOUR_API_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"rankings": ["atp", "wta"], "maxItemsPerRanking": 10}'
```

JavaScript (apify-client):

```javascript
import { ApifyClient } from 'apify-client';

const client = new ApifyClient({ token: 'YOUR_API_TOKEN' });
const run = await client.actor('automation-lab/sofascore-tennis-atp-wta-utr-ranking-lists').call({
    rankings: ['atpLive', 'wtaLive'],
    maxItemsPerRanking: 50,
});
const { items } = await client.dataset(run.defaultDatasetId).listItems();
console.log(items.map((p) => `${p.rank}. ${p.playerName} ${p.points}`));
```

Python (apify-client):

```python
from apify_client import ApifyClient

client = ApifyClient("YOUR_API_TOKEN")
run = client.actor("automation-lab/sofascore-tennis-atp-wta-utr-ranking-lists").call(
    run_input={"rankings": ["utrMen", "utrWomen"], "maxItemsPerRanking": 100}
)
for player in client.dataset(run["defaultDatasetId"]).iterate_items():
    print(player["rank"], player["playerName"], player["points"])
```

### Use with AI agents via MCP

Use the Actor-specific Apify MCP endpoint:

`https://mcp.apify.com?tools=automation-lab/sofascore-tennis-atp-wta-utr-ranking-lists`

#### Claude Code

```bash
claude mcp add --transport http apify \
  "https://mcp.apify.com?tools=automation-lab/sofascore-tennis-atp-wta-utr-ranking-lists"
```

#### Claude Desktop, Cursor and VS Code

```json
{
  "mcpServers": {
    "apify": {
      "url": "https://mcp.apify.com?tools=automation-lab/sofascore-tennis-atp-wta-utr-ranking-lists"
    }
  }
}
```

Example prompts:

- "Get the ATP live ranking top 20 and list who gained the most places."
- "Show every Spanish player in the WTA top 500 with rank and points."
- "Compare the UTR men top 10 with the official ATP top 10."

Discover the actual tool names and schemas with `tools/list`; selecting this Actor also adds run and storage helper tools. Start a run once and keep its run ID. `call-actor` waits at most 45 seconds, so if the run is not finished, check the same run with `get-actor-run` using bounded backoff (2, 4, 8, then at most 10 seconds) and a total deadline such as 120 seconds; at the deadline report the run as pending with its ID instead of starting another run.

After success, read results with `get-dataset-items` using explicit `limit`, `offset` and `fields` (for example `rank,playerName,countryAlpha3,points,rankChange`). A sensible consumer budget is pages of 20 rows, at most 100 rows and 64 KiB of serialized results in model context; keep complete exports outside the model context and report partial results with the next offset. These are consumer context limits, not Actor limits, and no token-savings guarantee is made.

### Is it legal to scrape SofaScore rankings?

The Actor reads publicly visible ranking tables without logging in. Rankings are public sporting facts, but you are responsible for using the data in line with SofaScore's terms and applicable laws, especially for commercial redistribution. This independent Actor is not affiliated with or endorsed by SofaScore, the ATP, the WTA or UTR Sports.

Failed operations send sanitized diagnostic input, exceptions and Actor/build/run IDs to our private GlitchTip service so we can fix problems. Secret fields and URL queries are removed; reports are retained for 30 days. Only public ranking paths are requested, through SofaScore or Google's public translation proxy. No AI is used during a run and no personal data beyond public athlete names and nationalities is collected.

### FAQ

**What is the difference between ATP and ATP live?**

The official ATP list is updated weekly. The live list adds points from tournaments in progress, so it changes during the week. In the live lists, `previousRank` is the player's current official rank, and `nextWinPoints` / `maxPoints` show what a player still in a tournament can reach.

**Why are UTR points decimals?**

UTR lists rank players by their Universal Tennis Rating (for example 16.45), which `points` contains for those lists.

**Why do I get fewer rows than my limit?**

SofaScore publishes up to 500 players per list, and the country filter keeps only matching players. The `OUTPUT` record shows rows available, rows matching and rows saved per list. A filter with no matching players saves no rows for that list and logs a warning.

**The run failed with "All SofaScore surfaces failed". What should I do?**

SofaScore or its public mirrors were unreachable for that list. Rows from other lists are kept. Retry later; if it keeps failing, open an issue on the Actor page with the run link.

**Can I get doubles rankings or match results?**

No. This Actor exports singles ranking lists only. For live matches and tournament results use the related Actors below.

### Related Actors

- [SofaScore Live Tennis Scraper](https://apify.com/automation-lab/sofascore-live-tennis-scraper) for matches being played right now.
- [Sofascore Tennis Tournaments Scraper](https://apify.com/automation-lab/sofascore-tennis-tournaments) for tournament metadata, seasons and match results.
- [SofaScore Live Events & Statistics Scraper](https://apify.com/automation-lab/sofascore-live-events-statistics-scraper) for live events and statistics across sports.

# Changelog

This Actor's version history is a separate document: https://apify.com/automation-lab/sofascore-tennis-atp-wta-utr-ranking-lists/changelog.md

# Actor input Schema

## `rankings` (type: `array`):

Which ranking lists to export. ATP and WTA are the official weekly singles rankings; ATP live and WTA live include points from tournaments in progress; UTR men and UTR women are Universal Tennis Ratings (points are the UTR rating, e.g. 16.45). Each list holds up to 500 players. Duplicates are ignored.

## `countryCodes` (type: `array`):

Only keep players whose nationality matches one of these codes. Use ISO 2-letter (ES, US) or 3-letter (ESP, USA) codes; matching is exact and case-insensitive, and any code in the list matches. Leave empty to keep every player. Ranks stay the players' world ranks; the max-players limit counts only matching players.

## `maxItemsPerRanking` (type: `integer`):

Maximum players saved from each selected list, counted after the country filter, in source order (No. 1 first). The limit applies to each list separately, so 2 lists with 100 means up to 200 rows. SofaScore publishes up to 500 players per list; set 500 or more to export a complete list.

## Actor input object example

```json
{
  "rankings": [
    "atp",
    "wta"
  ],
  "countryCodes": [],
  "maxItemsPerRanking": 20
}
```

# Actor output Schema

## `overview` (type: `string`):

One row per ranked player: list, rank, player, nationality, points, movement and player URL.

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

OUTPUT record with rows available, matched and saved per ranking list and the list update time.

# 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 = {
    "rankings": [
        "atp",
        "wta"
    ],
    "maxItemsPerRanking": 20
};

// Run the Actor and wait for it to finish
const run = await client.actor("automation-lab/sofascore-tennis-atp-wta-utr-ranking-lists").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 = {
    "rankings": [
        "atp",
        "wta",
    ],
    "maxItemsPerRanking": 20,
}

# Run the Actor and wait for it to finish
run = client.actor("automation-lab/sofascore-tennis-atp-wta-utr-ranking-lists").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 '{
  "rankings": [
    "atp",
    "wta"
  ],
  "maxItemsPerRanking": 20
}' |
apify call automation-lab/sofascore-tennis-atp-wta-utr-ranking-lists --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,automation-lab/sofascore-tennis-atp-wta-utr-ranking-lists"
        }
    }
}
```

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/QaZ8NmzidqkA74uok/builds/MlHUSFcmXtmIcRdtn/openapi.json
