OpenDota API endpoint
Returns a Dota 2 hero's benchmark percentiles from OpenDota's public games: for each of ten per-minute metrics (`gold_per_min`, `xp_per_min`, `kills_per_min`, `deaths_per_min`, `assists_per_min`, `last_hits_per_min`, `denies_per_min`, `hero_damage_per_min`, `hero_healing_per_min`, `tower_damage`) the value at percentiles 0.1 to 0.99, sorted by percentile. An unknown hero id returns 404.
/opendota/benchmarksHeader: x-api-key required.
Parameters:
hero_id: required positive hero id from opendota-heroes.bracket: optional rank bracket to benchmark against, 1 (Herald) to 8 (Immortal), the same eight brackets as opendota-rank-distribution; omit it for all ranks. The response repeats it in bracket with its name in bracket_name. It can be combined with role. A sparse bracket (for example 8) can report null points for a hero; those are dropped rather than shown as zeros, and a bracket with no data at all returns 404.role: optional role of the games counted; allowed values: core, support. Omit it for all roles. The role changes the numbers a lot (Anti-Mage's 30th-percentile gold per minute was 567 as core and 264 as support on 2026-10-29); the response repeats it in role. Any other value returns 400.Notable response behavior:
gold_per_min, xp_per_min, kills_per_min, deaths_per_min, assists_per_min, last_hits_per_min, denies_per_min, hero_damage_per_min, hero_healing_per_min and tower_damage, sorted by name; each has points at percentiles 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 0.95 and 0.99.404. The response is cached for up to six hours.| Field | Filled in, of 10 checked | Values in the sample |
|---|---|---|
| metric | 10 | “assists_per_min” and 9 other values |
| points | 10 | median 11 entries |
| Parameter | Type | Required | Default | Description | Example |
|---|---|---|---|---|---|
| x-api-key (header) | string | Yes | API key required | ||
| hero_id | integer | Yes | Positive hero ID from opendota-heroes | 1 | |
| bracket | integer | No | Rank bracket 1 (Herald) to 8 (Immortal) to benchmark against; omit for all ranks Minimum: 1. Maximum: 8. | ||
| role | string | No | Role of the games counted; one of core, support; omit for all roles Allowed values: core, support. |
curl -X GET "https://api.crawlora.net/api/v1/opendota/benchmarks?hero_id=1&role=core" \ -H "x-api-key: $CRAWLORA_API_KEY"
{
"code": 200,
"msg": "OK",
"data": {
"source_url": "https://api.opendota.com/api/benchmarks",
"fetched_at": "2026-10-28T10:00:00Z",
"hero_id": 1,
"hero_name": "Anti-Mage",
"count": 1,
"benchmarks": [
{
"metric": "gold_per_min",
"points": [
{
"percentile": 0.5,
"value": 545.5
},
{
"percentile": 0.99,
"value": 762
}
]
}
]
}
}Request schema
No body schema
Response schema
Inline response schema
| Field | Type | Required | Enum | Bounds | Example | Description |
|---|---|---|---|---|---|---|
| code | integer | No | Code is the HTTP status code or a custom code used to indicate the result of the request @example 200 | |||
| data | opendota.BenchmarksResponse | No | ||||
| data.benchmarks | array | No | ||||
| data.benchmarks[].metric | string | No | gold_per_min | |||
| data.benchmarks[].points | array | No | ||||
| data.benchmarks[].points[].percentile | number | No | 0.5 | |||
| data.benchmarks[].points[].value | number | No | 545.5 | |||
| data.bracket | integer | No | 4 | |||
| data.bracket_name | string | No | Archon | |||
| data.count | integer | No | 10 | |||
| data.fetched_at | string | No | 2026-10-27T10:00:00Z | |||
| data.hero_id | integer | No | 1 | |||
| data.hero_name | string | No | Anti-Mage | |||
| data.role | string | No | core, support | core | ||
| data.source_url | string | No | ||||
| msg | unknown | No | Msg is the message that describes the result of the request @example "Request successful" |
| Status | Description | Schema |
|---|---|---|
| 400 | Bad Request | #/definitions/app.Response |
| 404 | Not Found | #/definitions/app.Response |
| 429 | Too Many Requests | #/definitions/app.Response |
| 503 | Service Unavailable | #/definitions/app.Response |
Use environment variables for secrets and keep Crawlora API keys server-side.
curl -X GET "https://api.crawlora.net/api/v1/opendota/benchmarks?hero_id=1&role=core" \
-H "x-api-key: $CRAWLORA_API_KEY"