Runner Stats
Full individual runner profiles covering career, distance, condition, spell, weight, running style, form trends, and more.
Pro only
This endpoint requires a Professional or Enterprise subscription.
GET
/v1/stats/runner/searchPro
Search Runners
Search for runners by name. Use this to find the runnerId needed for the full stats endpoint below.
Parameters
qstringrequired
Partial runner name (minimum 3 characters).
race_codestringoptional
Default: gallopsRace type filter:
gallops, harness, or greyhounds.countrystringoptional
Optional country filter (e.g.
au, nz, hk, gb, us).Code Examples
javascript
const response = await fetch(
'https://api.formfav.com/v1/stats/runner/search?' +
new URLSearchParams({ q: 'via sistina', race_code: 'gallops' }),
{
headers: { 'X-API-Key': 'your_api_key_here' }
}
);
const data = await response.json();Response Fields
querystringThe search query used
resultsarrayMatching runners, ordered by total starts
results[].runnerIdintegerRunner ID (use with the stats endpoint)
results[].namestringRunner name
results[].raceTypestringRace type: R (thoroughbred), H (harness), G (greyhound)
results[].countrystring | nullCountry code (3-letter ISO)
results[].totalStartsinteger | nullCareer total starts
results[].lastRaceDatestring | nullDate of most recent race (YYYY-MM-DD)
results[].sirestring | nullSire name
results[].damstring | nullDam name
Example Response
200
Responsejson
{
"query": "via sistina",
"results": [
{
"runnerId": 8734,
"name": "Via Sistina",
"raceType": "R",
"country": "AUS",
"totalStarts": 16,
"lastRaceDate": "2025-10-25",
"sire": "Fastnet Rock",
"dam": "Viareggio"
}
]
}GET
/v1/stats/runner/{runner_id}Pro
Runner Stats Profile
Returns a comprehensive stats profile for a runner. Use /stats/runner/search first to find the runner ID.
Parameters
runner_idintegerrequired
Runner ID (path parameter). Obtain via the search endpoint.
windowintegeroptional
Optional rolling window in days (14–365). When provided, a
recentStats object is included with stats computed only from races within the window.Code Examples
javascript
const response = await fetch(
'https://api.formfav.com/v1/stats/runner/4521?' +
new URLSearchParams({ window: '90' }),
{
headers: { 'X-API-Key': 'your_api_key_here' }
}
);
const data = await response.json();Response Fields
runnerobjectRunner identity
runner.runnerIdintegerRunner ID
runner.namestringRunner name
runner.raceTypestringRace type (R, H, G)
runner.countrystring | nullCountry code
runner.sexstring | nullSex (e.g. Mare, Gelding)
runner.sirestring | nullSire name
runner.damstring | nullDam name
runner.ageinteger | nullAge in years
runner.daysSinceLastRuninteger | nullDays since last race
runner.lastRaceDatestring | nullDate of most recent race
careerobjectCareer summary
career.totalStartsintegerTotal career starts
career.winsintegerTotal wins
career.secondsintegerTotal seconds
career.thirdsintegerTotal thirds
career.winRatenumberWin rate (0-1)
career.placeRatenumberPlace rate (0-1)
career.firstStartstring | nullDate of first career start
career.lastStartstring | nullDate of last career start
distanceStatsarrayPerformance by distance
distanceStats[].distanceMetersintegerDistance in meters
distanceStats[].totalStartsintegerStarts at this distance
distanceStats[].winsintegerWins
distanceStats[].winRatenumberWin rate
distanceStats[].placeRatenumberPlace rate
conditionStatsarrayPerformance by track condition
conditionStats[].conditionstringTrack condition (e.g. good, soft, heavy)
conditionStats[].totalStartsintegerStarts in this condition
conditionStats[].winsintegerWins
conditionStats[].winRatenumberWin rate
conditionStats[].placeRatenumberPlace rate
trackDistanceStatsarrayPerformance by track + distance combination
trackDistanceStats[].venuestringVenue name
trackDistanceStats[].distanceMetersintegerDistance in meters
trackDistanceStats[].totalStartsintegerStarts
trackDistanceStats[].winsintegerWins
trackDistanceStats[].winRatenumberWin rate
spellStatsarrayPerformance by runs since spell
spellStats[].runsSinceSpellinteger1 = first-up, 2 = second-up, etc.
spellStats[].totalStartsintegerStarts
spellStats[].winsintegerWins
spellStats[].winRatenumberWin rate
spellStats[].placeRatenumberPlace rate
boxStatsarrayPerformance by box/barrier (greyhounds)
boxStats[].boxNumberintegerBox number
boxStats[].totalStartsintegerStarts from this box
boxStats[].winsintegerWins
boxStats[].winRatenumberWin rate
jockeyStatsarrayPerformance by jockey partnership
jockeyStats[].jockeyNamestringJockey name
jockeyStats[].totalStartsintegerStarts together
jockeyStats[].winsintegerWins together
jockeyStats[].winRatenumberWin rate
classProfileobject | nullClass level analysis
classProfile.currentRatinginteger | nullMost recent class rating (0-100)
classProfile.peakRatinginteger | nullHighest class ever competed at
classProfile.highestClassWoninteger | nullHighest class where runner won
classProfile.optimalRangeMininteger | nullLower bound of optimal class range
classProfile.optimalRangeMaxinteger | nullUpper bound of optimal class range
classProfile.trendstring | nullClass trend: rising, stable, dropping
weightProfileobject | nullWeight carrying analysis (thoroughbreds)
weightProfile.avgWeightnumber | nullAverage weight carried
weightProfile.avgWeightWhenWinningnumber | nullAverage weight when winning
weightProfile.optimalWeightLownumber | nullLower bound of optimal weight range
weightProfile.optimalWeightHighnumber | nullUpper bound of optimal weight range
weightProfile.recentWeightTrendstring | nullRecent weight trend
runningStyleobject | nullRunning style profile
runningStyle.runningStylestringL=Leader, P=Presser, M=Midfield, B=Backmarker, X=Unrated. Built per race code as described in Speed Map
runningStyle.earlySpeedIndexnumberEarly speed, 0-10 (higher = quicker early). Draw-adjusted for harness: 5 = typical for its draws. 0 when unrated
runningStyle.finishingStylestring | nullHow the runner finishes. Gallops only
runningStyle.gateSpeedstring | nullSpeed out of the gates. Gallops only
runningStyle.isVersatilebooleanCan race different styles. Gallops only; always false for greyhounds and harness
formTrendobject | nullForm trend analysis
formTrend.trendDirectionstringimproving, declining, stable, peaking, recovering
formTrend.trendStrengthnumberStrength of trend (0-1)
formTrend.formMomentumnumberWeighted recent form score
formTrend.last5WinRatenumberWin rate from last 5 starts
formTrend.last10WinRatenumberWin rate from last 10 starts
formTrend.currentWinStreakintegerCurrent consecutive wins
formTrend.currentPlaceStreakintegerCurrent consecutive placings
formTrend.currentUnplacedStreakintegerCurrent consecutive unplaced runs
formTrend.consistencyRatingnumberConsistency rating (higher = more consistent)
formTrend.avgDaysBetweenRunsnumber | nullAverage days between races
venueStatsarrayPerformance by venue
venueStats[].venuestringVenue name
venueStats[].totalStartsintegerStarts at venue
venueStats[].winsintegerWins
venueStats[].winRatenumberWin rate
venueStats[].placeRatenumberPlace rate
venueStats[].bestFinishinteger | nullBest finish position
trialFormobject | nullTrial form summary
trialForm.totalTrialsintegerTotal trials
trialForm.trialWinsintegerTrial wins
trialForm.trialWinRatenumberTrial win rate
trialForm.lastTrialDatestring | nullDate of last trial
trialForm.improvingTrialFormbooleanWhether trial form is improving
railPreferenceobject | nullRail position preference
railPreference.trueRailStartsintegerStarts on true rail
railPreference.trueRailWinRatenumberWin rate on true rail
railPreference.outRailStartsintegerStarts on out rail
railPreference.outRailWinRatenumberWin rate on out rail
railPreference.railPreferencestringtrue, out, neutral, or insufficient_data
sireProfileobject | nullSire statistics
sireProfile.sireNamestringSire name
sireProfile.totalProgenyintegerTotal progeny count
sireProfile.winRatenumberProgeny win rate
sireProfile.bestDistanceCategorystring | nullBest distance category
sireProfile.debutWinRatenumber | nullProgeny debut win rate
seasonalStatsarrayPerformance by month
seasonalStats[].monthintegerMonth number (1-12)
seasonalStats[].totalStartsintegerStarts in this month
seasonalStats[].winRatenumberWin rate
seasonalStats[].isPeakPeriodbooleanWhether this is a peak performance month
recentStatsobject | nullRecent-window stats (only when
window param provided)recentStats.windowDaysintegerWindow size in days
recentStats.totalStartsintegerStarts in window
recentStats.winsintegerWins in window
recentStats.winRatenumberWin rate in window
recentStats.placeRatenumberPlace rate in window
recentStats.trackStatsarrayPer-track breakdown in window
recentStats.conditionStatsarrayPer-condition breakdown in window
recentStats.distanceStatsarrayPer-distance breakdown in window
Example Response
200
Responsejson
{
"runner": {
"runnerId": 8734,
"name": "Via Sistina",
"raceType": "R",
"country": "AUS",
"sex": "Mare",
"sire": "Fastnet Rock",
"dam": "Viareggio",
"age": 5,
"daysSinceLastRun": 14,
"lastRaceDate": "2025-10-25"
},
"career": {
"totalStarts": 16,
"wins": 10,
"seconds": 3,
"thirds": 1,
"winRate": 0.625,
"placeRate": 0.875,
"firstStart": "2023-08-19",
"lastStart": "2025-10-25"
},
"distanceStats": [
{ "distanceMeters": 1600, "totalStarts": 8, "wins": 6, "seconds": 1, "thirds": 0, "winRate": 0.750, "placeRate": 0.875 },
{ "distanceMeters": 2000, "totalStarts": 5, "wins": 3, "seconds": 1, "thirds": 1, "winRate": 0.600, "placeRate": 1.0 }
],
"conditionStats": [
{ "condition": "good", "totalStarts": 12, "wins": 8, "places": 11, "winRate": 0.667, "placeRate": 0.917 }
],
"formTrend": {
"trendDirection": "peaking",
"trendStrength": 0.88,
"formMomentum": 8.5,
"last5WinRate": 0.8,
"last10WinRate": 0.7,
"currentWinStreak": 4,
"currentPlaceStreak": 6,
"currentUnplacedStreak": 0,
"bestWinStreak": 4,
"consistencyRating": 0.89,
"finishStdDev": 0.41,
"daysSincePeakForm": null,
"avgDaysBetweenRuns": 28,
"optimalSpellLength": 21
},
"venueStats": [
{ "venue": "Randwick", "totalStarts": 14, "wins": 13, "places": 14, "winRate": 0.929, "placeRate": 1.0, "bestFinish": 1, "firstStart": "2015-04-04", "lastStart": "2019-04-13" }
],
"recentStats": null
}