Equibase Scraper - Horse Racing Entries, Results & Charts API avatar

Equibase Scraper - Horse Racing Entries, Results & Charts API

Pricing

from $6.23 / 1,000 results

Go to Apify Store
Equibase Scraper - Horse Racing Entries, Results & Charts API

Equibase Scraper - Horse Racing Entries, Results & Charts API

Extract US and Canadian Thoroughbred racing data from Equibase: race entries with jockey, trainer, owner, sire and dam, finished results with win-place-show and exotic payoffs, and horse profiles with career records.

Pricing

from $6.23 / 1,000 results

Rating

0.0

(0)

Developer

ParseForge

ParseForge

Maintained by Community

Actor stats

0

Bookmarked

7

Total users

4

Monthly active users

6 days ago

Last modified

Share

ParseForge

Equibase Scraper - Horse Racing Entries, Results & Charts API

Scrape North American Thoroughbred racing from Equibase, the official data source of the sport. Get tomorrow's entries with every horse's jockey, trainer, owner, sire, dam and morning line; get yesterday's results with the full order of finish, win-place-show and every exotic payoff; get any horse's career record. 71 fields, no login, no API key. Export to CSV, JSON, Excel, or XML.

Equibase has no free public API, and its data pages sit behind Imperva bot protection that answers a plain HTTP request with HTTP 200 and a block page — which is how a scraper ends up reporting a successful run with an empty dataset. This Actor drives a real browser through the challenge and checks every page by content, never by status code.

Who uses itWhat they scrape Equibase for
Handicappers and betting modelsFull fields with morning lines, post positions, weights and medication, the morning the entries drop
Racing analytics and data productsResults with finish order, final times, and every exotic pool payoff in one schema
Bloodstock and breeding researchSire, dam and dam sire on every entry, plus career earnings and speed figures per horse
Racing media and tipping servicesWhole cards, every track, ready to publish without manual entry
Ownership and syndicate platformsOwner and breeder on every runner, joined by a stable horse id

What it does

Pick one of three result types and the Actor returns flat rows.

🏇 Race entries — one row per horse declared: program number, post position, age, sex, medication, assigned weight, jockey, trainer, owner, breeder, sire, dam, dam sire, and the morning line in both fraction and decimal.

🏁 Race results — one row per finisher: finish position, win, place and show payoffs, the winning connections, the final time and going, plus every exotic pool — exacta, trifecta, superfecta, Pick N — attached to the winning row.

📋 Horse profiles — one row per horse: lifetime starts, wins, placings and earnings, best Equibase Speed Figure, season-by-season splits and the complete past-performance list.

Every run also gives you:

  • 🗓️ Whole cards or whole meets. Name a track and a date, a date range, or nothing at all to take every track racing that day.
  • 📏 Distances normalised to yards. Equibase writes "Five And One Half Furlongs" on entries and "5 1/2 F" on results; both come back as distanceYards: 1210.
  • 🟫 Surface on every race. Entries only annotate turf and synthetic, so an unannotated race is reported as Dirt — a rule checked against the results page for the same card and right on all ten races.
  • ✂️ Scratches handled properly. A scratched horse is a differently shaped table row on Equibase; it is flagged isScratched, keeps its name and morning line, and never has another horse's jockey pasted onto it.
  • 🔗 Stable ids to join on. horseRefNumber, jockeyId and trainerId come straight from Equibase and survive name spellings.

Results export to CSV, JSON, Excel, or XML, or stream from the API.

What you can do with Equibase data

📊 Build a handicapping model.

Entries give you the whole field with weights, medication, post positions and the morning line; results give you what actually happened. Join them on horseRefNumber and raceDate.

🎯 Track a trainer or jockey.

Filter every card at every track by trainer or jockey and get their runners, prices and finishes without opening a single page.

🧬 Study a sire's progeny.

Sire, dam and dam sire on every entry make it one filter to pull every runner by a given stallion across the country.

💰 Model payoff structure.

Exotic payoffs with the winning combinations let you measure pool behaviour, favourite-longshot bias, and carryover value.

Why choose this scraper

What you get
Gets past the bot wallEquibase's Imperva protection returns HTTP 200 on a block. This Actor drives a real browser through a residential exit and verifies every page by content, so a blocked page is never mistaken for an empty card — and a blocked page is never charged.
Three result typesEntries, results and horse profiles, in one Actor and one schema.
71 fieldsEverything Equibase publishes on the page, including owner, breeder and full pedigree on every runner.
Connections and pedigree per horseOwner, breeder, sire, dam and dam sire, matched to each runner by program number. Optional, so you only pay for them when you want them.
Payoffs, not just finishersWin, place and show on the finishers that earned them, and every exotic pool on the winning row.
Distances you can compute withdistanceYards alongside the prose, so races compare across both of Equibase's spellings.
17 filters that cut the billRace number, surface, purse, breed, stakes, claiming, jockey, trainer, owner, horse, sex, age and scratches. Filtered rows are never written and never charged.
Predictable billOne per-row price by default. Connections, pedigree, exotic payoffs and race history are each a checkbox that is off until you tick it, so a run cannot surprise you with charges you did not ask for.
Honest emptiesA field Equibase does not publish is absent, never a guessed value and never a null.
Four export formatsCSV, JSON, Excel, and XML, from the dashboard or the API.

How it compares

There is one other Equibase Actor in the Store. The competitor column reflects what its own public listing states, not a test run of it.

FeatureParseForgejungle_synthesizer
Race entriesYesYes
Race results and payoffsYes, including every exotic poolYes, finish order, times, payouts
Horse career profilesYesNot stated
Owner and breeder per runnerYesNot stated
Sire, dam and dam sireYesNot stated
Scratched horses handledFlagged, and never column-shiftedNot stated
Distance normalised to yardsYesNot stated
Filter before you pay17 filtersNot stated
Date range across a meetYes, using each track's own calendarAny date and track
Actor start fee$0.02 per GB$0.10
Base price per row$0.007$0.001

Come here when you need the connections, the pedigree, the exotic payoffs, or scratch handling you can trust.

What an entry looks like

Every runner returns as one flat JSON row. Here is a real record, unedited:

{
"rowType": "entry",
"trackCode": "DMR",
"trackName": "Del Mar",
"country": "USA",
"raceDate": "2026-08-20",
"raceNumber": 1,
"raceName": "Del Mar ALLOWANCE OPTIONAL CLAIMING $80,000",
"raceType": "ALLOWANCE OPTIONAL CLAIMING",
"purse": 81000,
"distance": "Five Furlongs",
"distanceYards": 1100,
"surface": "Turf",
"claimingPrice": 80000,
"ageRestriction": "Three Year Olds",
"isStakes": false,
"isClaiming": true,
"wagers": ["$1 Exacta", "$2 Quinella", "50c Trifecta"],
"programNumber": "1",
"postPosition": 1,
"horse": "Dr. My Eyes",
"horseState": "LA",
"horseRefNumber": "11306737",
"horseUrl": "https://www.equibase.com/profiles/Results.cfm?type=Horse&refno=11306737&registry=T&rbt=TB",
"age": 3,
"sex": "C",
"medication": "L",
"weight": 121,
"jockey": "K Kimura",
"jockeyId": "164186",
"trainer": "P D'Amato",
"trainerId": "277836",
"morningLineOdds": "3/1",
"morningLineDecimal": 4,
"owner": "Intrepid Thoroughbreds LLC",
"breeder": "Coteau Grove Farms, LLC",
"sire": "Maxfield",
"dam": "You Caught My Eye",
"damSire": "Can the Man",
"isScratched": false,
"entryUrl": "https://www.equibase.com/static/entry/DMR082026USA-EQB.html",
"scrapedAt": "2026-08-20T14:05:53.732Z"
}

And a result row, with the payoffs on the winner:

{
"rowType": "result",
"trackName": "Del Mar",
"raceDate": "2026-08-15",
"raceNumber": 1,
"raceType": "Maiden Special Weight",
"purse": 80000,
"distance": "1 M",
"distanceYards": 1760,
"surface": "Dirt",
"trackCondition": "Fast",
"postTime": "2:01",
"finalTime": "1:37.79",
"finishPosition": 1,
"programNumber": "6",
"horse": "Harmonique",
"winPayoff": 15.8,
"placePayoff": 5.6,
"showPayoff": 3.2,
"winningOwner": "Thor-Bred Stables LLC",
"winningTrainer": "Neil D. Drysdale",
"winningJockey": "Joel Rosario",
"exoticWagers": [{ "wagerType": "$1 Exacta", "winningNumbers": "6-5", "payoff": 14.5 }]
}

Configure the run

SettingWhat it does
resultTypeentries, results, or horses.
tracksEquibase codes (DMR, SAR, CD) or full names (Del Mar). Empty takes every track with a card that day.
dateOne race day, YYYY-MM-DD. Defaults to today for entries, and to each track's most recent card for results.
dateFrom / dateToAn inclusive range. Days a track did not race are skipped using its own calendar, so they cost nothing.
maxDaysCeiling on race days fetched per track. Each day is one page load through the challenge, so this is the main lever on run time.
countryUSA, CAN or PUR. Canadian tracks such as Woodbine need CAN.
horseUrlsHorse profile URLs or bare reference numbers, for resultType: horses.
maxItemsCeiling on rows written.
includeConnections, includePedigree, includeWagers, includeRaceHistoryOptional data blocks, all off by default. Each adds fields to the row and is billed separately — see Pricing.
proxyConfigurationResidential proxy, on by default. Equibase refuses datacenter addresses — see below.

Narrow the run with filters

Every filter runs before the row is written, so rows you filter out are never charged.

FilterWhat it keeps
raceNumbersOnly these races on the card.
surfacesDirt, Turf, All Weather, Steeplechase.
minPurse / maxPurseRaces inside a purse range.
onlyStakesStakes, handicaps, derbies, cups and graded races.
onlyClaimingRaces where horses can be claimed.
breedsThoroughbred, Quarter Horse and the rest, by Equibase's code.
horseNameRunners whose name contains your text.
jockey / trainer / ownerRunners with that connection. Substring match, because Equibase abbreviates first names on entries.
sexesColt, filly, gelding, horse, mare, ridgling.
minAge / maxAgeHorses inside an age range.
excludeScratchedDrops horses withdrawn from the card.

Why it needs a browser and a residential proxy

Equibase's Imperva protection makes two separate demands, and both were measured on 20/08/2026.

It wants the challenge executed. Plain HTTP requests are refused whatever IP they come from: all four Apify proxy groups — none, datacenter, residential and Unblocker — were tried against the same three URLs and all four were blocked identically, always with HTTP 200. Replaying the reese84 cookie that a browser mints does not help either, because Imperva fingerprints the TLS handshake as well. Only a real browser navigation gets through, and only a real navigation: fetch() from inside the page is refused too, because Imperva reads Sec-Fetch-Dest.

It also refuses datacenter addresses. A browser running on an Apify datacenter IP is blocked however long it waits. That is why the residential proxy is on by default — on this site it is not a tuning knob, it is the difference between rows and an empty dataset.

To keep the proxy bill down, images, fonts, media and stylesheets are dropped on the way in. That takes a card from about 9.8 MB of traffic to about 1.8 MB, and the challenge still clears — scripts are never blocked, because the challenge is a script.

Pricing

This Actor is pay per event, and a run left at its defaults has exactly one per-row price. Every optional data block is off by default: if you do not tick it, you do not receive it and you are not charged for it. Nothing is billed for rows a filter rejected, and a page Equibase never let us read is not billed either.

EventPriceWhen it fires
result-item$0.007One row. Covers the race and its conditions, purse, distance and surface, plus the horse, jockey, trainer, weight and odds — or the finish position with win, place and show payoffs.
race-page$0.045One track-and-day page loaded through the anti-bot challenge, however many races the card holds.
horse-profile$0.03One horse profile page loaded through the challenge.
calendar-scan$0.01One track calendar read, so days the track did not race cost nothing.
apify-actor-start$0.02Once when the run starts, per GB of memory.

Optional, and off unless you ask for them:

EventPriceSwitched on by
connections$0.0012includeConnections — owner and breeder on a runner, winning connections on a result.
pedigree$0.0012includePedigree — sire, dam and dam sire.
wager-payoffs$0.002includeWagers — exacta, trifecta, superfecta and Pick N payoffs.
race-history$0.003includeRaceHistory — the full past-performance list on a horse profile.

A default full card — one page, ninety runners — costs $0.675. Switch on connections and pedigree and the same card is $0.891.

The page and profile events are priced where they are because each one is a real browser navigation through an anti-bot challenge, not an HTTP request.

Free users

Apify free-plan runs are capped at 50 rows per run, because every page costs a full browser load. Everything else works the same: all 71 fields, all 17 filters, all three result types, and every optional block available to tick. Upgrade your Apify plan to lift the cap.

Run it

  1. Open the Actor in Apify Console, pick a result type, and put a track code in tracks.
  2. Set maxItems to the number of rows you want.
  3. Click Start, then export the dataset as CSV, JSON, Excel, or XML.

Or from the API:

curl -X POST "https://api.apify.com/v2/acts/parseforge~equibase-scraper/runs?token=YOUR_TOKEN" \
-H 'Content-Type: application/json' \
-d '{"resultType":"entries","tracks":["DMR"],"maxItems":100}'

Use with AI agents (MCP)

The Actor is exposed over Apify's MCP server, so an agent can call it as a tool:

https://mcp.apify.com/sse?actors=parseforge/equibase-scraper

Ask things like "who is running at Del Mar today and what are the morning lines" and the agent fills the input itself.

Troubleshooting

No rows came back.

The most common cause is a date with no card. A track only has entries on days it races — check its calendar, or leave date empty and let the Actor use today for entries and the last published card for results.

"No card published" in the log.

Equibase returns a 404 for a track-and-day with no race. That is the source's real state, and it is not charged.

Why is surface "Dirt" when the page says nothing?

Equibase only annotates turf and synthetic surfaces on entries. An unannotated race runs on the main dirt track. The rule was checked against the results page for the same card, which does state the surface, and it was right on all ten races.

Why does a scratched horse have no jockey?

Equibase collapses the jockey, trainer, weight and medication of a scratched horse into a single dashed cell. The name and the morning line survive, and the row is flagged isScratched. Nothing is invented to fill the gap.

Why is medication or claimingPrice empty?

Not every horse runs on medication and not every race is a claimer. An absent field is a real absence.

Why is the run slow?

Each track-and-day is one browser navigation through a residential exit, and the anti-bot challenge needs a few seconds to clear before the page is readable. Lower maxDays, or name specific tracks instead of taking every card in the country.

The log says pages were blocked.

Imperva blocks per IP. The Actor already retries each page three times, taking a fresh browser session and a new exit IP each time, and a page it never managed to read is not charged. If a whole run is blocked, check that the residential proxy is enabled in the input and run it again.

A field stopped filling.

Equibase changed its page markup. Email us with your run ID so we can update the parser.

FAQ

QuestionAnswer
Do I need an Equibase account or API key?No. This reads public Equibase pages, so there is nothing to register or authenticate.
Does it cover Canada?Yes. Set country to CAN for Woodbine and the other Canadian tracks.
Does it cover harness racing or Quarter Horses?Equibase publishes them and they come through the same schema. Use the breeds filter to keep or drop them.
Can I get a whole meet in one run?Yes. Set dateFrom and dateTo and raise maxDays. Days the track did not race are skipped for free.
Are live tote odds included?No. The morning line is, in both fraction and decimal. Equibase's live-odds column mirrors the morning line outside live wagering, so it is not shipped as a field that would always be empty.
Can I join entries to results?Yes. horseRefNumber is on both, and it is Equibase's own permanent id.
How many rows per run?Free plan: 50. Paid: up to 100,000, bounded by how many runners your tracks and dates actually contain.
Does it need a proxy?Yes, residential, and it is on by default. Equibase refuses datacenter addresses even to a real browser. Plain HTTP is refused from every IP, proxied or not.
Is this an official Equibase product?No. It is unofficial and reads only publicly available Equibase pages.

Browse the full ParseForge collection for more scrapers.

🆘 Need help? Email parseforge@protonmail.com with your run ID, your input, and what you expected.

⚠️ Disclaimer. This Actor is unofficial and is not affiliated with, endorsed by, or sponsored by Equibase Company LLC, The Jockey Club, or any racing authority. It collects only publicly available Equibase data. Equibase asserts copyright over its racing data; you are responsible for using it in compliance with Equibase's terms and applicable law, and for obtaining a licence where your use requires one. Race results are public sporting records.