# Equibase Scraper - Horse Racing Entries & Results (`bovi/equibase-scraper`) Actor

Scrape Equibase horse racing data: race entries with horse, jockey, trainer, post position and morning line, plus race results with order of finish, win-place-show payoffs, exotic payoffs, also-rans and scratches. No login.

- **URL**: https://apify.com/bovi/equibase-scraper.md
- **Developed by:** [Vitalii Bondarev](https://apify.com/bovi) (community)
- **Categories:** Other, Developer tools
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $0.80 / 1,000 equibase scraper - horse racing entries & results

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.

Learn more: https://docs.apify.com/actors/running/actors-in-store.md#pay-per-event

## What's an Apify Actor?

An Actor is a serverless cloud program that runs on the Apify platform. It has two run modes.
In Batch mode, an Actor accepts a well-defined JSON input, performs an action which can take anything from a few seconds to a few hours,
and optionally produces a well-defined JSON output, datasets with results, or files in key-value store.
In Standby mode, an Actor provides a web server which can be used as a website, API, or an MCP server.

Apify vocabulary and the platform model are defined once, in the agent quickstart at https://apify.com/agents.md.

## How to integrate an Actor?

If asked about integration, you help developers integrate Actors into their projects.
You adapt to their stack and deliver integrations that are safe, well-documented, and production-ready.

Do not guess an integration path. Every one of them is in the agent quickstart at https://apify.com/agents.md: the Apify MCP server, Agent Skills with the Apify CLI, the JavaScript and Python clients, the REST API, and the account-free path for an agent with no human to sign in. It also carries the rule on stating cost before the first paid run.

For examples already wired to this Actor's own input schema, see the [API](#api) section below.

Each client library has reference documentation the quickstart does not restate: [JavaScript/TypeScript](https://docs.apify.com/api/client/js/docs.md) (`npm install apify-client`) and [Python](https://docs.apify.com/api/client/python/docs.md) (`pip install apify-client`).

# README

## Equibase Scraper - Horse Racing Entries & Results

Collect North American Thoroughbred racing data from Equibase, the official data source of the sport, without a login or an API key. The Actor reads the public Equibase mobile pages, which are plain HTML and are not behind the bot-challenge wall that guards the main site's entry and result pages, so it runs fast and cheaply with ordinary HTTP requests.

### What it collects

Pick one of two result types. Every record is one flat JSON row.

- **Race entries** - one row per horse declared in a race: track, date, race number, post time, race conditions, program number, post position, horse name, jockey, trainer and the morning line.
- **Race results** - one row per horse in a finished race: the top three finishers with finish position and win, place and show payoffs for a $2 bet, the exotic payoffs (exacta, trifecta, superfecta, daily double, Pick N and so on) attached to the winner's row, the also-ran horses and the scratched horses.

Only fields that Equibase really publishes on these pages are returned. A value that is not on the page is left out, never guessed. Horse career profiles, owner, breeder, sire and dam are not available on the public pages and are not part of this Actor.

### Input

| Field | Meaning |
| --- | --- |
| `resultType` | `entries` or `results`. |
| `tracks` | Track codes (`BEL`, `KEE`, `SA`) or names (`Belmont Park`). Empty means every track with a card. |
| `date` | One race day, `YYYY-MM-DD`. |
| `dateFrom`, `dateTo` | Inclusive date range. |
| `maxDays` | Race days read per track (default 1). Equibase lists about the last five days of results and the next few days of entries. |
| `maxResults` | Maximum number of records (default 50). The run stops as soon as it is reached. |
| `proxyConfiguration` | Optional. Public pages normally work without a proxy. |

Example input:

```json
{
  "resultType": "entries",
  "tracks": ["BEL"],
  "maxDays": 1,
  "maxResults": 50
}
```

### Example output

Entry row:

```json
{
  "trackCode": "BEL",
  "track": "Belmont Park",
  "raceDate": "2026-10-15",
  "raceNumber": 3,
  "postTime": "2:16",
  "raceType": "Allowance Optional Claiming",
  "programNumber": "1",
  "postPosition": 1,
  "morningLine": "9/2",
  "horseName": "Sherlock's Jewel",
  "jockey": "Kendrick Carmouche",
  "trainer": "Joe Sharp",
  "url": "https://mobile.equibase.com/html/entriesBEL2026101503.html",
  "scrapedAt": "2026-10-14T08:00:00+00:00"
}
```

Result row (winner):

```json
{
  "trackCode": "BEL",
  "track": "Belmont Park",
  "raceDate": "2026-10-11",
  "raceNumber": 7,
  "postTime": "4:33",
  "raceName": "Starter Allowance",
  "outcome": "finished",
  "finishPosition": 1,
  "programNumber": "1",
  "horseName": "Our Preferred Pal",
  "winPayoff": 25.64,
  "placePayoff": 11.9,
  "showPayoff": 4.88,
  "exotics": [{"betType": "Exacta", "combination": "1-4", "payoff": 65.34}]
}
```

### Price

You pay per result: each dataset item (one horse row) is billed by the platform at the price shown on the Actor page, and nothing else. Use `maxResults` to cap the cost of a run.

### Notes

The Actor waits half a second between requests to stay polite. Post times are shown as Equibase prints them, in the track's local time.

# Actor input Schema

## `resultType` (type: `string`):

Entries are the horses declared for a card, with jockey, trainer and morning line. Results are the order of finish with win, place and show payoffs and exotic payoffs.

## `tracks` (type: `array`):

Equibase track codes (BEL, KEE, SA...) or track names ("Belmont Park"). Leave empty to take every track that has a card.

## `date` (type: `string`):

A single race day as YYYY-MM-DD. Leave empty to take the most recent days Equibase lists.

## `dateFrom` (type: `string`):

Start of an inclusive date range, YYYY-MM-DD.

## `dateTo` (type: `string`):

End of the inclusive date range, YYYY-MM-DD.

## `maxDays` (type: `integer`):

Ceiling on how many race days are read per track. Equibase lists roughly the last five results days and the next few entry days.

## `maxResults` (type: `integer`):

Maximum number of records to collect.

## `proxyConfiguration` (type: `object`):

Optional. The pages are public and normally work without a proxy.

## Actor input object example

```json
{
  "resultType": "entries",
  "tracks": [],
  "maxDays": 1,
  "maxResults": 50,
  "proxyConfiguration": {
    "useApifyProxy": true,
    "apifyProxyGroups": [
      "RESIDENTIAL"
    ]
  }
}
```

# Actor output Schema

## `results` (type: `string`):

Dataset with the scraped records.

# API

You can run this Actor programmatically using our API. Below are code examples in JavaScript, Python, and CLI, as well as the OpenAPI specification and MCP server setup.

## JavaScript example

```javascript
import { ApifyClient } from 'apify-client';

// Initialize the ApifyClient with your Apify API token
// Replace the '<YOUR_API_TOKEN>' with your token
const client = new ApifyClient({
    token: '<YOUR_API_TOKEN>',
});

// Prepare Actor input
const input = {
    "resultType": "entries",
    "proxyConfiguration": {
        "useApifyProxy": true,
        "apifyProxyGroups": [
            "RESIDENTIAL"
        ]
    }
};

// Run the Actor and wait for it to finish
const run = await client.actor("bovi/equibase-scraper").call(input);

// Fetch and print Actor results from the run's dataset (if any)
console.log('Results from dataset');
console.log(`💾 Check your data here: https://console.apify.com/storage/datasets/${run.defaultDatasetId}`);
const { items } = await client.dataset(run.defaultDatasetId).listItems();
items.forEach((item) => {
    console.dir(item);
});

// 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/js/docs

```

## Python example

```python
from apify_client import ApifyClient

# Initialize the ApifyClient with your Apify API token
# Replace '<YOUR_API_TOKEN>' with your token.
client = ApifyClient("<YOUR_API_TOKEN>")

# Prepare the Actor input
run_input = {
    "resultType": "entries",
    "proxyConfiguration": {
        "useApifyProxy": True,
        "apifyProxyGroups": ["RESIDENTIAL"],
    },
}

# Run the Actor and wait for it to finish
run = client.actor("bovi/equibase-scraper").call(run_input=run_input)

# Fetch and print Actor results from the run's dataset (if there are any)
print(f"💾 Check your data here: https://console.apify.com/storage/datasets/{run.default_dataset_id}")
for item in client.dataset(run.default_dataset_id).iterate_items():
    print(item)

# 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/python/docs/quick-start

```

## CLI example

```bash
echo '{
  "resultType": "entries",
  "proxyConfiguration": {
    "useApifyProxy": true,
    "apifyProxyGroups": [
      "RESIDENTIAL"
    ]
  }
}' |
apify call bovi/equibase-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,bovi/equibase-scraper"
        }
    }
}
```

The hosted server signs you in with OAuth on first connect, so no API token belongs in this config. Clients without OAuth support can send an `Authorization: Bearer <APIFY_API_TOKEN>` header instead, using a token from API & Integrations in Apify Console (https://console.apify.com/settings/integrations).

## OpenAPI specification

Download the OpenAPI definition: https://api.apify.com/v2/actors/e1ku2NLTUCrhWhQWP/builds/tkCOfUJZIym90QdUf/openapi.json
