/v1/stats/track-bias/{venue}Track Bias
Returns barrier draw bias statistics for a venue, showing which barrier positions historically produce above or below average win rates — for the track as a whole, per distance band, or scoped to a distance you choose.
Pro only
Barrier bias is distance-specific
distanceStats, the same barrier breakdown for every distance band run at that venue. To analyse one race, pass distance (e.g. 1200 or 1200-1600) and the whole report is scoped to those races.Parameters
venuestringrandwick, flemington).race_codestringgallopsgallops, harness or greyhounds. For greyhounds, barrier numbers are box positions (1–8).countrystringauau, nz, hk, gb).distancestring1200) matches that exact distance; a range (1200-1600) is inclusive and lets you build your own band — narrower than a preset, or spanning several. See Distance Bands. Valid range 200–5000. When supplied, the top-level barrierStats, strongestBarrier, weakestBarrier and biasStrength describe only those races, distanceFilter echoes the scope, and distanceStats holds a single Custom entry for the slice. Combines with window.windowintegerrecentStats object is included with barrier bias stats computed only from races within the window (and within distance, if given).conditionstringGood, Soft, Heavy). Only applies when window is also provided.Distance Bands
With no distance parameter, distanceStats contains one entry per band below that the venue actually runs, shortest first. Band labels depend on race_code. Each entry reports the real shortest and longest race distance the venue has run within that band (minDistance / maxDistance), so a “Sprint” band at a track that only runs 1000m and 1200m shows 1000–1200, not the band’s theoretical edges.
| Band | Gallops | Harness | Greyhounds |
|---|---|---|---|
| Sprint | <1400m | — | ≤450m |
| Medium | — | — | 451–565m |
| Distance | — | — | 566m+ |
| Mile | 1400–1799m | <1800m | — |
| Middle | 1800–2199m | 1800–2399m | — |
| Classic | 2200–2599m | — | — |
| Staying | 2600–3200m | 2400–2899m | — |
| Long | — | 2900m+ | — |
| Marathon | over 3200m (jumps races land here) | — | — |
Custom ranges
The preset bands are a starting point. If you want a different slice — one exact distance, a tighter band, or a wider one that merges two presets — pass it as distance and the whole report is computed for exactly those races:
distance=1200— only 1200m races (a single value is an exact match)distance=1000-1200— a tighter band than the preset Sprintdistance=1400-2200— merges Mile and Middle into one banddistance=500-525withrace_code=greyhounds— the two common middle-distance box lengths together
Ranges are inclusive at both ends, in metres, and must fall within 200–5000. Anything else (a reversed range, a unit suffix, a value outside the bounds) returns a 422 with the reason. When distance is supplied, distanceStats contains one entry with category: "Custom" mirroring the top-level report; its minDistance / maxDistance are the shortest and longest distances actually run inside your range, so distance=1600-2200 at a track with no races between 2000m and 2200m reports 1600–2000. Add window to also get a recent-form version of the same slice in recentStats.
Code Examples
const response = await fetch(
'https://api.formfav.com/v1/stats/track-bias/randwick?' +
new URLSearchParams({
race_code: 'gallops',
distance: '1200-1600'
}),
{
headers: { 'X-API-Key': 'your_api_key_here' }
}
);
const data = await response.json();Response Fields
venuestringraceTypestringtotalRacesintegerexpectedWinRatenumberbarrierStatsarraydistance was supplied.barrierStats[].barrierNumberintegerbarrierStats[].totalStartsintegerbarrierStats[].winsintegerbarrierStats[].placesintegerbarrierStats[].winRatenumberbarrierStats[].placeRatenumberbarrierStats[].advantagenumberstrongestBarrierintegerweakestBarrierintegerbiasStrengthstringdistanceStatsarraydistance was supplied, a single Custom entry mirroring the scoped top-level report.distanceStats[].categorystringCustom for a distance-scoped reportdistanceStats[].minDistanceintegerdistanceStats[].maxDistanceintegerdistanceStats[].totalRacesintegerdistanceStats[].expectedWinRatenumberdistanceStats[].barrierStatsarraydistanceStats[].strongestBarrierintegerdistanceStats[].weakestBarrierintegerdistanceStats[].biasStrengthstringdistanceFilterobject | nulldistance scoped the reportdistanceFilter.minDistanceintegerdistanceFilter.maxDistanceintegerconditionStatsarrayconditionStats[].conditionstringconditionStats[].totalRacesintegerconditionStats[].avgFieldSizenumber | nullrecentStatsobject | nullwindow param provided). Scoped by distance when given.recentStats.windowDaysintegerrecentStats.totalRacesintegerrecentStats.expectedWinRatenumberrecentStats.barrierStatsarrayrecentStats.strongestBarrierintegerrecentStats.weakestBarrierintegerrecentStats.biasStrengthstringrecentStats.conditionstring | nullExample Response
{
"venue": "Randwick",
"raceType": "R",
"totalRaces": 12570,
"expectedWinRate": 0.05,
"barrierStats": [
{ "barrierNumber": 1, "totalStarts": 1040, "wins": 108, "places": 312, "winRate": 0.1038, "placeRate": 0.3, "advantage": 0.0538 },
{ "barrierNumber": 2, "totalStarts": 1036, "wins": 96, "places": 290, "winRate": 0.0927, "placeRate": 0.2799, "advantage": 0.0427 },
{ "barrierNumber": 3, "totalStarts": 1029, "wins": 112, "places": 301, "winRate": 0.1088, "placeRate": 0.2925, "advantage": 0.0588 }
],
"strongestBarrier": 3,
"weakestBarrier": 20,
"biasStrength": "strong",
"conditionStats": [
{ "condition": "Good", "totalRaces": 653, "avgFieldSize": 10.4 },
{ "condition": "Soft", "totalRaces": 310, "avgFieldSize": 10.1 }
],
"distanceStats": [
{
"category": "Sprint",
"minDistance": 1000,
"maxDistance": 1300,
"totalRaces": 5569,
"expectedWinRate": 0.0588,
"barrierStats": [
{ "barrierNumber": 1, "totalStarts": 470, "wins": 54, "places": 152, "winRate": 0.1149, "placeRate": 0.3234, "advantage": 0.0561 }
],
"strongestBarrier": 1,
"weakestBarrier": 15,
"biasStrength": "moderate"
},
{
"category": "Mile",
"minDistance": 1400,
"maxDistance": 1609,
"totalRaces": 5014,
"expectedWinRate": 0.05,
"barrierStats": [
{ "barrierNumber": 1, "totalStarts": 418, "wins": 40, "places": 121, "winRate": 0.0957, "placeRate": 0.2895, "advantage": 0.0457 }
],
"strongestBarrier": 3,
"weakestBarrier": 20,
"biasStrength": "strong"
}
],
"distanceFilter": null,
"recentStats": null
}Example Response (scoped by distance)
GET /v1/stats/track-bias/randwick?distance=1200 — the top-level report now describes only 1200m races, and distanceStats carries the same slice as a single Custom entry.
{
"venue": "Randwick",
"raceType": "R",
"totalRaces": 2582,
"expectedWinRate": 0.0588,
"barrierStats": [
{ "barrierNumber": 1, "totalStarts": 236, "wins": 27, "places": 78, "winRate": 0.1144, "placeRate": 0.3305, "advantage": 0.0556 },
{ "barrierNumber": 2, "totalStarts": 234, "wins": 21, "places": 69, "winRate": 0.0897, "placeRate": 0.2949, "advantage": 0.0309 }
],
"strongestBarrier": 1,
"weakestBarrier": 15,
"biasStrength": "strong",
"conditionStats": [
{ "condition": "Good", "totalRaces": 653, "avgFieldSize": 10.4 }
],
"distanceStats": [
{
"category": "Custom",
"minDistance": 1200,
"maxDistance": 1200,
"totalRaces": 2582,
"expectedWinRate": 0.0588,
"barrierStats": [
{ "barrierNumber": 1, "totalStarts": 236, "wins": 27, "places": 78, "winRate": 0.1144, "placeRate": 0.3305, "advantage": 0.0556 },
{ "barrierNumber": 2, "totalStarts": 234, "wins": 21, "places": 69, "winRate": 0.0897, "placeRate": 0.2949, "advantage": 0.0309 }
],
"strongestBarrier": 1,
"weakestBarrier": 15,
"biasStrength": "strong"
}
],
"distanceFilter": { "minDistance": 1200, "maxDistance": 1200 },
"recentStats": null
}