Dota 2 и её данные: как достать матч через OpenDota API
Каждый матч Dota 2 оставляет след в открытых данных: пики, урон, тайминги. Разбираем, как вытащить эту статистику через OpenDota API и не упереться в лимиты запросов.

Каждая завершённая игра в Dota 2 превращается в структуру данных: 10 героев, десятки тысяч событий, тайминги фарма, деталь по каждому предмету. Valve отдаёт часть этого через свой Steam Web API, но работать с ним неудобно. Поэтому большинство аналитиков и разработчиков идут в OpenDota — открытый проект, который парсит реплеи и отдаёт результат обычным JSON по HTTP. Ниже — как забрать матч, распарсить его и не словить бан по лимиту.
Откуда берутся данные о матче
Есть два уровня детализации. Базовый приходит сразу после игры: победа/поражение, KDA, золото, опыт, купленные предметы. Расширенный (тайминги, тепловые карты движения, лог событий) появляется только после того, как реплей матча скачан и распарсен — этим занимается парсер OpenDota, но не для всех матчей автоматически.
Если расширенных данных нет, вы можете запросить парсинг сами — об этом ниже. Важно понимать разницу: свежий публичный матч почти всегда доступен в базовом виде, а разбор реплея может занять от секунд до минут в зависимости от очереди.
Что нужно, чтобы начать
- Match ID — числовой идентификатор матча (виден в клиенте Dota 2 в истории игр).
- Любой HTTP-клиент:
curl,requests,fetch. - Опционально — API-ключ OpenDota, если бесплатного лимита не хватает.
Первый запрос: один матч
Базовый эндпоинт возвращает всё, что известно о конкретном матче. Match ID подставляется прямо в путь:
curl "https://api.opendota.com/api/matches/7891234567"
В ответе — большой JSON. Ключевые поля верхнего уровня:
radiant_win—true, если победила сторона Radiant;duration— длительность матча в секундах;players— массив из 10 объектов, по одному на игрока;picks_bans— порядок пиков и банов (только в матчах с драфтом).
Внутри каждого игрока лежат hero_id, kills, deaths, assists, gold_per_min, xp_per_min, массив purchase_log с таймингами предметов. Именно purchase_log и gold_t (золото по минутам) есть только у распарсенных матчей.
Пример на Python
import requests
MATCH_ID = 7891234567
url = f"https://api.opendota.com/api/matches/{MATCH_ID}"
resp = requests.get(url, timeout=10)
resp.raise_for_status()
data = resp.json()
winner = "Radiant" if data["radiant_win"] else "Dire"
print(f"Победа: {winner}, длительность: {data['duration'] // 60} мин")
for p in data["players"]:
print(
p.get("hero_id"),
f"{p['kills']}/{p['deaths']}/{p['assists']}",
"GPM", p["gold_per_min"],
)
Обратите внимание на hero_id: это число, а не имя. Чтобы получить «Anti-Mage» вместо 1, подтяните справочник героев из отдельного эндпоинта /api/heroes один раз и держите его в кеше — он меняется редко.
Лимиты и ключ
OpenDota работает по фримиум-модели. Без ключа доступ бесплатный, но ограничен по частоте — публично заявлен потолок порядка нескольких запросов в секунду и суточный лимит на бесплатном уровне. Точные значения OpenDota периодически меняет, поэтому актуальные цифры и тарифы сверяйте на их странице документации, а не по чужим статьям.
Если вы делаете пакетную выгрузку сотен матчей, ключ почти обязателен: он поднимает лимиты и даёт предсказуемость. Ключ передаётся параметром запроса ?api_key=ВАШ_КЛЮЧ.
Главная ошибка новичка — гонять цикл по тысяче Match ID без пауз и без обработки кода 429. Через минуту вы получаете сплошные отказы и решаете, что «API сломался». Он не сломался — вы упёрлись в rate limit.
Как не словить 429
- Ставьте паузу между запросами (например,
time.sleep(1)) или используйте очередь с ограничением. - Обрабатывайте статус
429 Too Many Requests— при нём делайте экспоненциальную задержку и повтор. - Кешируйте всё, что уже скачали: матч по одному ID не меняется, второй запрос за тем же — пустая трата лимита.
- Для больших объёмов смотрите в сторону эндпоинта
/api/explorerс SQL-запросами вместо тысяч отдельных обращений.
Запросить разбор реплея
Если у матча нет расширенных полей, отправьте POST на эндпоинт парсинга — он поставит матч в очередь:
curl -X POST "https://api.opendota.com/api/request/7891234567"
В ответ придёт идентификатор задачи. После завершения парсинга повторный GET по матчу вернёт уже полные тайминги. Реплей должен быть доступен на серверах Valve — старые матчи Valve со временем удаляет, и тогда распарсить их нельзя.
Куда смотреть дальше
| Эндпоинт | Что отдаёт | Когда нужен |
|---|---|---|
/api/matches/{id} | Полные данные одного матча | Разбор конкретной игры |
/api/players/{id} | Профиль и агрегаты игрока | Статистика по аккаунту |
/api/heroes | Справочник героев | Мэппинг hero_id в имена |
/api/explorer | Произвольный SQL по базе | Массовые выборки |
Для одноразового анализа хватит первого эндпоинта и справочника героев. Для дашборда или исследования по тысячам матчей стройте пайплайн вокруг /api/explorer: один продуманный SQL-запрос заменяет сотни точечных обращений и экономит лимит.
Важно: OpenDota — сторонний проект, а не сервис Valve. Он может менять формат ответа, лимиты и набор полей без предупреждения. Перед тем как завязывать на него продакшн, заложите в код обработку отсутствующих полей и версионирование ответа.
Prompt-инженер: Идеальные запросы для Midjourney, ChatGPT и других моделей.
Спросить за 15 ₽Источники: OpenDota API Documentation, Steam Web API — Dota 2 (Valve Developer)
Частые вопросы
Чем OpenDota отличается от официального Steam Web API?
Нужен ли API-ключ для нескольких запросов?
Почему у матча нет таймингов золота и предметов?
Можно ли достать данные о матче, которому несколько лет?
Как получить имя героя вместо hero_id?
Что делать, если начали приходить ошибки 429?
Материал носит информационный характер и подготовлен редакцией «Агентуры». Он не является офертой, рекламой или индивидуальной консультацией. Упомянутые продукты, компании и торговые знаки принадлежат их правообладателям. Перед принятием решений, влекущих юридические или финансовые последствия, обратитесь к профильному специалисту.