# HLTV Scraper (`solidcode/hltv-scraper`) Actor

\[💰 $4.00 / 1K] Scrape CS2 esports matches from HLTV.org — upcoming, live, and past results. Get teams, scores, maps won, event, match format (bo1/bo3/bo5), star rating, and start time. Optional per-match map veto, lineups, streams, and head-to-head. JSON, CSV, Excel exports.

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

## Pricing

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

## HLTV Scraper

Pull Counter-Strike 2 match data from HLTV.org at scale — upcoming schedules, live scores, and finished results, complete with teams, world rankings, map vetoes, player lineups, streams, and head-to-head history. Built for esports analysts, betting and odds researchers, CS2 data scientists, and content creators who need structured match data without refreshing HLTV's match pages by hand.

### Why This Scraper?

- **All three match states in one actor** — upcoming, live, and finished results, or blend them together with "All". Live matches carry running per-map scores as the series plays out.
- **0–5 star importance filter** — HLTV's own event-significance rating on every match; set the minimum to 5 to isolate only tier-1 tournament matches (Majors and top-tier LANs).
- **Full best-of veto breakdown** — the complete ordered pick/ban sequence, per-map round scores, and which team picked each map across bo1, bo3, and bo5 series.
- **Both starting lineups with player IDs** — two 5-man rosters per match, each player's nickname, real name, nationality, and HLTV profile link.
- **Live stream directory per match** — every listed stream with its watch URL, current viewer count, and broadcast country.
- **Head-to-head history** — the two teams' prior meetings with dates, maps, scores, and the running win tally, ready for form and matchup analysis.
- **World ranking and country on both teams** — HLTV's global team ranking, country/region, and team IDs pulled from each match's own page (turn on full match details), so you can weight matchups by tier.
- **Target by team, event, or match URL** — paste a team page to pull all its matches, an event page for a full tournament's bracket, or a single match link; HLTV IDs are resolved automatically.
- **ISO-8601 start times plus epoch timestamps** — every match carries a timezone-safe scheduled start and the raw Unix-millisecond value, so schedules sort and convert cleanly across regions.

### Use Cases

**Esports Analytics & Scouting**

- Build team form tables from head-to-head history and recent results
- Study map-pick tendencies and veto patterns ahead of a match
- Compare starting lineups and world rankings across a tournament bracket
- Track which maps a team consistently wins or loses on

**Betting & Odds Research**

- Assemble upcoming match slates with star ratings and best-of formats
- Pull head-to-head win tallies to model matchups
- Follow live per-map scores as series unfold
- Backtest strategies against a full archive of finished results

**Content & Community**

- Auto-generate match-day schedules and previews for a CS2 site or Discord
- Surface tier-1 (5-star) matches worth streaming or covering
- Pull stream links and viewer counts for watch guides
- Build "results roundup" posts from finished matches

**Data Science & Research**

- Compile historical match datasets for model training
- Analyze best-of format (bo1/bo3/bo5) trends across events
- Study world-ranking movement and roster changes over time
- Feed structured match data into dashboards and notebooks

### Getting Started

#### Upcoming Matches (simple)

The quickest start — the next scheduled matches on HLTV:

```json
{
    "matchType": "upcoming",
    "maxResults": 50
}
```

#### Top Finished Results with Full Details

Recent results for important events only, each enriched with maps, veto, lineups, streams, and head-to-head:

```json
{
    "matchType": "results",
    "minStars": "3",
    "scrapeMatchDetails": true,
    "maxResults": 100
}
```

#### Target a Team or Event by URL

Paste an HLTV team or event URL to pull all of its matches, fully detail-enriched:

```json
{
    "startUrls": [
        "https://www.hltv.org/team/4494/mouz"
    ],
    "scrapeMatchDetails": true,
    "maxResults": 50
}
```

### Input Reference

#### What to Scrape

| Parameter | Type | Default | Description |
|-----------|------|---------|-------------|
| `matchType` | select | `Upcoming matches` | Which matches to collect: `Upcoming matches`, `Live matches`, `Past results`, or `All (upcoming + live + results)`. Ignored when you paste Start URLs below. |
| `startUrls` | string\[] | `[]` | Optional. Paste HLTV URLs to target directly: individual match pages, event pages (all matches of a tournament), or team pages (a team's matches). Takes priority over Match Type. |

#### Filters

| Parameter | Type | Default | Description |
|-----------|------|---------|-------------|
| `minStars` | select | `Any (0+)` | Only include matches at or above this importance rating: `Any (0+)`, `1+ stars`, `2+ stars`, `3+ stars`, `4+ stars`, or `5 stars only`. HLTV rates each match 0–5 stars by event significance. |

#### Detail Data

| Parameter | Type | Default | Description |
|-----------|------|---------|-------------|
| `scrapeMatchDetails` | boolean | `false` | Open each match's page to collect per-map veto and scores, both team lineups, live streams, and recent head-to-head. Leave off for a fast overview of teams, event, format, stars, and start time. |

#### Limits

| Parameter | Type | Default | Description |
|-----------|------|---------|-------------|
| `maxResults` | integer | `100` | Cap on the total number of matches returned — the run stops at exactly this many. Set to `0` for no cap. Maximum 50,000; higher values (and `0`) are capped to 50,000. |

### Output

Each row is one match. Basic fields come from the listing; the detail fields (maps, veto, lineups, streams, head-to-head) are filled when **Scrape full match details** is on, and always for matches reached via Start URLs. Here is a finished, fully detailed match:

```json
{
    "matchId": 2380001,
    "url": "https://www.hltv.org/matches/2380001/mouz-vs-vitality-blast-premier-world-final-2025",
    "status": "finished",
    "live": false,
    "startTime": "2025-06-14T17:00:00+00:00",
    "startTimestamp": 1749920400000,
    "format": "bo3",
    "stars": 5,
    "eventName": "BLAST Premier World Final 2025",
    "eventId": 7148,
    "team1Name": "MOUZ",
    "team2Name": "Vitality",
    "team1Id": 4494,
    "team2Id": 9565,
    "team1Country": "Europe",
    "team2Country": "France",
    "team1Ranking": 3,
    "team2Ranking": 1,
    "team1Score": 1,
    "team2Score": 2,
    "winner": "Vitality",
    "team1Logo": "https://img-cdn.hltv.org/teamlogo/example1.svg",
    "team2Logo": "https://img-cdn.hltv.org/teamlogo/example2.svg",
    "maps": [
        { "name": "Mirage", "team1Score": 13, "team2Score": 9, "pickedBy": "MOUZ" },
        { "name": "Inferno", "team1Score": 8, "team2Score": 13, "pickedBy": "Vitality" },
        { "name": "Nuke", "team1Score": 11, "team2Score": 13, "pickedBy": null }
    ],
    "vetoProcess": [
        "1. MOUZ removed Ancient",
        "2. Vitality removed Anubis",
        "3. MOUZ picked Mirage",
        "4. Vitality picked Inferno",
        "5. MOUZ removed Dust2",
        "6. Vitality removed Train",
        "7. Nuke was left over"
    ],
    "team1Players": [
        { "playerId": 19230, "nickname": "torzsi", "name": "Ádám Torzsás", "country": "Hungary", "profileUrl": "https://www.hltv.org/player/19230/torzsi" },
        { "playerId": 18960, "nickname": "Brollan", "name": "Ludvig Brolin", "country": "Sweden", "profileUrl": "https://www.hltv.org/player/18960/brollan" }
    ],
    "team2Players": [
        { "playerId": 11893, "nickname": "ZywOo", "name": "Mathieu Herbaut", "country": "France", "profileUrl": "https://www.hltv.org/player/11893/zywoo" },
        { "playerId": 19899, "nickname": "apEX", "name": "Dan Madesclaire", "country": "France", "profileUrl": "https://www.hltv.org/player/19899/apex" }
    ],
    "streams": [
        { "name": "BLAST Premier", "url": "https://www.twitch.tv/blastpremier", "viewers": 184203, "country": "United Kingdom" }
    ],
    "headToHead": [
        { "date": "2025-03-09", "matchUrl": "https://www.hltv.org/matches/2379500/vitality-vs-mouz-iem-katowice-2025", "team1": "Vitality", "team2": "MOUZ", "event": "IEM Katowice 2025", "map": "Dust2", "result": "13-7" }
    ],
    "scrapedAt": "2026-07-16T14:30:00+00:00"
}
```

#### Core Match Fields

| Field | Type | Description |
|-------|------|-------------|
| `matchId` | integer | HLTV match id |
| `url` | string | Match page URL |
| `status` | string | `upcoming`, `live`, or `finished` |
| `live` | boolean | True while the match is in progress |
| `startTime` | string | Scheduled or actual start time, ISO 8601 |
| `startTimestamp` | integer | Start time as a Unix epoch (milliseconds) |
| `format` | string | Best-of format — `bo1`, `bo3`, or `bo5` |
| `stars` | integer | Event importance rating, 0–5 |
| `eventName` | string | Tournament / event name |
| `eventId` | integer | HLTV event id (null when unavailable) |
| `winner` | string | Winning team name (null until finished) |
| `scrapedAt` | string | ISO 8601 timestamp of extraction |

#### Teams

World ranking, country, and team IDs are read from each match's own page, so they fill when **Scrape full match details** is on (and always for pasted Start URLs); team IDs also appear on live and upcoming listing cards. Name, score, and logo come straight from the listing.

| Field | Type | Description |
|-------|------|-------------|
| `team1Name` / `team2Name` | string | Team names (null for undecided bracket matches) |
| `team1Id` / `team2Id` | integer | HLTV team ids (listing for live/upcoming; with full match details otherwise) |
| `team1Country` / `team2Country` | string | Team country or region (with full match details) |
| `team1Ranking` / `team2Ranking` | integer | HLTV world ranking (with full match details) |
| `team1Score` / `team2Score` | integer | Maps won (null before the match starts) |
| `team1Logo` / `team2Logo` | string | Team logo image URLs |

#### Detail: Maps & Veto

Populated when **Scrape full match details** is on (and always for pasted Start URLs).

| Field | Type | Description |
|-------|------|-------------|
| `maps` | object\[] | Per map: `name`, `team1Score`, `team2Score`, and `pickedBy` |
| `vetoProcess` | string\[] | Ordered pick/ban steps for the series |

#### Detail: Lineups

| Field | Type | Description |
|-------|------|-------------|
| `team1Players` / `team2Players` | object\[] | Each roster's players: `playerId`, `nickname`, `name` (real name), `country`, and `profileUrl` (HLTV player page link) |

#### Detail: Streams & Head-to-Head

| Field | Type | Description |
|-------|------|-------------|
| `streams` | object\[] | Live streams: `name`, `url`, `viewers`, and `country` |
| `headToHead` | object\[] | Prior meetings: `date`, `matchUrl`, `team1`, `team2`, `event`, `map`, and `result` |

### Tips for Best Results

- **Start with a small `maxResults`** — try 20–50 on your first run to confirm the fields match your needs, then scale up.
- **Set `minStars` to 5 to isolate tier-1 matches** — HLTV reserves 5 stars for the biggest Majors and top-tier LANs, so a 5-star filter strips out qualifiers and lower-tier events in a single move.
- **Leave details off for a fast schedule overview** — teams, event, format, stars, and start time all come straight from the listing. Turn details on only when you need veto, lineups, streams, or head-to-head.
- **Paste a team or event URL to go deep on one target** — a team page pulls all of that team's scheduled and recent matches; an event page pulls a full tournament's bracket, both fully detail-enriched.
- **Use "All" for a complete snapshot** — one run captures upcoming, live, and finished matches together, deduplicated across the boards.
- **Sort by `startTimestamp` downstream** — the raw epoch-millisecond field sorts cleanly in any tool, while `startTime` gives you a timezone-safe ISO string for display.
- **Undecided bracket matches are kept, not dropped** — many upcoming slots (e.g. "Group A Winners' Match") have a real match ID, event, and time but no teams yet; they appear with null team names so you can track the schedule before the bracket resolves.

### Pricing

**From $4.00 per 1,000 results** — undercuts the market rate for HLTV match extraction while bundling map veto, lineups, streams, and head-to-head at no extra charge. Bronze, Silver, and Gold subscribers pay progressively less; the table below shows the total cost at each discount tier.

| Results | No discount | Bronze | Silver | Gold |
|---------|-------------|--------|--------|------|
| 100 | $0.48 | $0.45 | $0.43 | $0.40 |
| 1,000 | $4.80 | $4.50 | $4.30 | $4.00 |
| 10,000 | $48.00 | $45.00 | $43.00 | $40.00 |
| 100,000 | $480.00 | $450.00 | $430.00 | $400.00 |

A "result" is any match row in the output dataset. No compute or time-based charges — you pay per result, plus a small fixed per-run start fee.

### Integrations

Export data in JSON, CSV, Excel, XML, or RSS. Connect to 1,500+ apps via:

- **Zapier** / **Make** / **n8n** — Workflow automation
- **Google Sheets** — Direct spreadsheet export
- **Slack** / **Email** — Notifications on new results
- **Webhooks** — Trigger custom APIs on run completion
- **Apify API** — Full programmatic access

### Legal & Ethical Use

This actor is designed for legitimate esports research, analytics, and content creation. Users are responsible for complying with applicable laws and HLTV.org's Terms of Service. Do not use extracted data for spam, harassment, or any illegal purpose, and respect content usage rules for any streams or profiles linked from a match page.

# Actor input Schema

## `matchType` (type: `string`):

Which matches to collect: upcoming (scheduled), live (in progress), results (finished), or all of them together. Ignored when you paste specific URLs below.

## `startUrls` (type: `array`):

Optional. Paste HLTV URLs to target specific matches directly: individual match pages (e.g. https://www.hltv.org/matches/2380000/...), event pages (all matches of a tournament), or team pages (a team's matches). When provided, these take priority over the Match Type above. Leave empty to use Match Type.

## `minStars` (type: `string`):

Only include matches with at least this importance rating. HLTV rates each match 0–5 stars based on the event's significance — 5 stars marks the biggest tournament matches. Leave at 'Any' to include everything.

## `scrapeMatchDetails` (type: `boolean`):

Turn on to open each match's page and collect extra data: per-map veto and scores, both team lineups (players and nationalities), live streams, and recent head-to-head history. Slower and billed per match — leave off for a fast overview of teams, event, format, stars, and start time.

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

Hard cap on the total number of matches returned — the run stops at exactly this many. Default 100 — increase for bigger runs, or set to 0 for no cap. The maximum is 50,000: any higher value (including 0 for no cap) is capped to 50,000 to prevent runaway pagination.

## Actor input object example

```json
{
  "matchType": "upcoming",
  "startUrls": [],
  "minStars": "0",
  "scrapeMatchDetails": false,
  "maxResults": 100
}
```

# Actor output Schema

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

Compact table of scraped matches — teams, event, format, stars, start time, and status.

## `details` (type: `string`):

Full match metadata including team IDs and rankings, scores, maps, player lineups, streams, and head-to-head.

# 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 = {
    "matchType": "upcoming",
    "startUrls": [],
    "minStars": "0",
    "scrapeMatchDetails": false,
    "maxResults": 100
};

// Run the Actor and wait for it to finish
const run = await client.actor("solidcode/hltv-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 = {
    "matchType": "upcoming",
    "startUrls": [],
    "minStars": "0",
    "scrapeMatchDetails": False,
    "maxResults": 100,
}

# Run the Actor and wait for it to finish
run = client.actor("solidcode/hltv-scraper").call(run_input=run_input)

# Fetch and print Actor results from the run's dataset (if there are any)
print("💾 Check your data here: https://console.apify.com/storage/datasets/" + run["defaultDatasetId"])
for item in client.dataset(run["defaultDatasetId"]).iterate_items():
    print(item)

# 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/python/docs/quick-start

```

## CLI example

```bash
echo '{
  "matchType": "upcoming",
  "startUrls": [],
  "minStars": "0",
  "scrapeMatchDetails": false,
  "maxResults": 100
}' |
apify call solidcode/hltv-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "command": "npx",
            "args": [
                "mcp-remote",
                "https://mcp.apify.com/?tools=solidcode/hltv-scraper",
                "--header",
                "Authorization: Bearer <YOUR_API_TOKEN>"
            ]
        }
    }
}

```

## OpenAPI specification

Download the OpenAPI definition: https://api.apify.com/v2/acts/xLLIPmb8mvTCgEuMa/builds/dB1NFS4v491C67iJo/openapi.json
