# LMArena Leaderboard Scraper — Elo ratings & rank changes (`istmobot/arena-ai-leaderboard-scraper`) Actor

Export every LMArena / arena.ai leaderboard (text, webdev, vision, text-to-image, image edit, search, video…) as structured JSON: rank, model, organization, license, Elo rating with confidence interval and votes. Track rank and rating changes between runs.

- **URL**: https://apify.com/istmobot/arena-ai-leaderboard-scraper.md
- **Developed by:** [Istmobot](https://apify.com/istmobot) (community)
- **Categories:** AI, Developer tools
- **Security:** Limited permissions
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

Pay per event

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.

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

## LMArena (arena.ai) Leaderboard Scraper — Elo ratings & rank changes

Export **every LMArena leaderboard** (now at arena.ai) as clean, structured JSON: rank, model, organization, license, **Elo rating with its confidence interval**, vote count and publish date — for text, WebDev, vision, text-to-image, image editing, search, document, video and more. Turn on **change tracking** and every row also tells you how far the model moved since your last run, and whether it is new on the board.

No browser, no login, no API key. One run reads all leaderboards in a few seconds.

### What it does

- **All leaderboards**: leave `categories` empty to get text, code/webdev, code/image-to-webdev, vision, text-to-image, image-edit, search, document, text-to-video, image-to-video and video-edit.
- **Official data source**: rows come from LMArena's own public dataset on Hugging Face ([lmarena-ai/leaderboard-dataset](https://huggingface.co/datasets/lmarena-ai/leaderboard-dataset), CC BY 4.0), so runs do not depend on arena.ai's bot protection.
- **Sub-categories** too: `text/coding`, `text/math`, `text/creative-writing`, `vision/ocr`, `text-to-image/portraits`, language boards such as `text/spanish`, etc.
- **Full rows**: rating + upper/lower confidence bounds, rank + rank range, votes, organization, license, model URL, input/output price per million tokens, context length.
- **Change tracking**: stores the previous snapshot of each board and outputs `rankChange`, `ratingChange` and `isNew` per row.
- **Top N** filter to keep just the head of each board.
- Reads the official dataset files directly (no HTML parsing), retries with exponential backoff on rate limits and server errors, one failed board never crashes the run.

### Use cases

- **AI product teams** — pick the best model per modality, and get alerted when a new model overtakes yours.
- **Investors & analysts** — track which labs are winning over time (OpenAI vs Google vs Anthropic vs open-source).
- **Newsletters & content creators** — weekly "who moved on LMArena" posts from a scheduled run.
- **Researchers** — build a historical dataset of Elo ratings and votes per model.
- **Dashboards** — pipe into Google Sheets, BigQuery or Looker via Apify integrations.

### Input

| Field | Type | Default | Description |
|---|---|---|---|
| `categories` | list of strings | empty (all) | Board names as in the URL: `text`, `code/webdev`, `vision`, `text-to-image`, `text/coding`… Full URLs work too |
| `topN` | integer | `0` | Only the top N rows per board. `0` = all ranked models |
| `trackChanges` | boolean | `false` | Compare with the previous run and fill the change fields |

```json
{
  "categories": ["text", "code/webdev", "vision", "text-to-image"],
  "topN": 50,
  "trackChanges": true
}
```

### Output

One item per model per leaderboard:

```json
{
  "category": "text",
  "rank": 2,
  "model": "gemini-4-argon-high",
  "modelDisplayName": "Gemini 4 Argon (High)",
  "organization": "google",
  "license": "Proprietary",
  "rating": 1520.25,
  "ratingUpper": 1526.53,
  "ratingLower": 1513.98,
  "votes": 11889,
  "rankUpper": null,
  "rankLower": null,
  "rankChange": 1,
  "ratingChange": 3.08,
  "isNew": false,
  "modelUrl": null,
  "inputPricePerMillion": null,
  "outputPricePerMillion": null,
  "contextLength": null,
  "publishDate": "2026-10-28",
  "previousSnapshotDate": "2026-10-22",
  "snapshotDate": "2026-11-05",
  "url": "https://arena.ai/leaderboard/text",
  "scrapedAt": "2026-11-05T22:00:00.000Z"
}
```

- `model` is a stable id derived from the model name; `modelDisplayName` is the name as published by LMArena (change tracking matches on `model`).
- `rating` is the arena score (style control on, as displayed by default). `ratingLower`/`ratingUpper` are the confidence bounds.
- `publishDate` is the date LMArena published this board in its dataset. `snapshotDate` is the UTC date of the run.
- `rankUpper`, `rankLower`, `modelUrl`, `inputPricePerMillion`, `outputPricePerMillion` and `contextLength` are always `null`: the official dataset does not include them. They stay in the output so existing integrations keep working.

#### Change fields

| Field | Meaning |
|---|---|
| `rankChange` | Positions gained since the previous snapshot. `+2` = climbed from #3 to #1, `-1` = dropped one place, `0` = unchanged |
| `ratingChange` | Rating difference vs the previous snapshot |
| `isNew` | `true` if the model wasn't on that board last time |

On the first run with `trackChanges` (the **baseline**) and when tracking is off, all three are `null`. Snapshots are kept in the named key-value store **`arena-leaderboard-snapshots`** in your Apify account (one key per board), so they persist across runs. Schedule the Actor daily or weekly (Apify Console → Schedules) for a running change log.

#### Error items

```json
{ "category": "agent", "url": "https://arena.ai/leaderboard/agent", "errorType": "NO_ROWS", "error": "No Elo leaderboard rows found — unknown leaderboard name, or a board that does not use Elo ratings (e.g. \"agent\")" }
```

`errorType` is `NO_ROWS` or `FETCH_FAILED`. Error items are **never charged**.

### Pricing

Pay-per-event:

- **Actor start** — small fixed fee per run.
- **`row-result`** — per leaderboard row in the output.

Use `topN` to pay only for the models you care about. Set a maximum cost per run and the Actor stops cleanly once it's reached.

### FAQ

**Is this the same as lmarena.ai?** Yes — LMArena (formerly Chatbot Arena by LMSYS) moved to arena.ai; lmarena.ai redirects there. Old `lmarena.ai` URLs are accepted as input.

**Why is the `agent` board skipped?** It ranks agents with a different, non-Elo scoring system (success signals instead of pairwise votes), so it doesn't fit this schema. If you request it explicitly you get a free `NO_ROWS` error item.

**How often do the leaderboards update?** As often as LMArena publishes to its dataset: typically every few days to a week for text and vision, less often for smaller boards. It can lag the live arena.ai page by a few days; check `publishDate` on each row. A daily or weekly schedule catches every published change.

**Does `topN` affect change tracking?** No. The full board is always saved as the snapshot, so models outside your top N aren't reported as "new" later.

**Why not scrape arena.ai directly?** The site now answers automated clients with a Cloudflare challenge. LMArena publishes the same leaderboards as an open dataset, which is simpler and more reliable. If the dataset can't be read you get a free `FETCH_FAILED` error item instead of bad data.

### Disclaimer

This is an **unofficial** tool and is **not affiliated with, endorsed by, or sponsored by LMArena, arena.ai or LMSYS**. It reads LMArena's public dataset on Hugging Face (CC BY 4.0) without logging in or bypassing any protections. Attribute LMArena when you reuse the data, and use it in line with the dataset license and applicable law.

# Actor input Schema

## `categories` (type: `array`):

Leaderboards to scrape, as shown in the arena.ai URL: text, code/webdev, vision, text-to-image, image-edit, search, document, text-to-video, image-to-video, video-edit, code/image-to-webdev. Sub-categories work too, e.g. text/coding. Leave empty to get all of these leaderboards.

## `topN` (type: `integer`):

Only output the top N models of each leaderboard. 0 = every ranked model.

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

Save a snapshot of each leaderboard and, on following runs, fill rankChange, ratingChange and isNew for every row. The first run creates the baseline (change fields are null). Schedule it daily or weekly.

## Actor input object example

```json
{
  "categories": [
    "text",
    "code/webdev",
    "vision",
    "text-to-image"
  ],
  "topN": 50,
  "trackChanges": false
}
```

# 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 = {
    "categories": [
        "text",
        "code/webdev",
        "vision",
        "text-to-image"
    ],
    "topN": 50
};

// Run the Actor and wait for it to finish
const run = await client.actor("istmobot/arena-ai-leaderboard-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 = {
    "categories": [
        "text",
        "code/webdev",
        "vision",
        "text-to-image",
    ],
    "topN": 50,
}

# Run the Actor and wait for it to finish
run = client.actor("istmobot/arena-ai-leaderboard-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 '{
  "categories": [
    "text",
    "code/webdev",
    "vision",
    "text-to-image"
  ],
  "topN": 50
}' |
apify call istmobot/arena-ai-leaderboard-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,istmobot/arena-ai-leaderboard-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/koM8Vjb2SEbU5Onme/builds/Sj5rnyyPkVuZvkhYL/openapi.json
