Discover/TAB API
live

TAB APItab.com.au

Retrieve horse racing meetings, race cards, fixed odds, and results from TAB Australia. Covers thoroughbred, harness, and greyhound racing across all states.

This API takes change requests — .
Endpoints
5
Verified account required
Updated
29d ago

What is the TAB API?

The TAB.com.au API exposes 5 endpoints covering Australian racing meetings, race cards, fixed odds, and results. Use get_racing_meetings_by_date to pull all meetings for a given day filtered by jurisdiction, or hit get_next_to_jump_races for a live feed of upcoming races across all venues and race types without specifying any parameters.

This call costs1 credit / call— charged only on success
Try it
Date in YYYY-MM-DD format. Defaults to today.
State jurisdiction code (NSW, VIC, QLD, etc.)
api.parse.bot/scraper/5137d70d-0c2b-4de4-a5a9-1554bd34c3e9/<endpoint>
Ready to send
Fill in the parameters and hit sign in to send to see live response data here.
Call it over HTTPgrab a free API key at signup
curl -X GET 'https://api.parse.bot/scraper/5137d70d-0c2b-4de4-a5a9-1554bd34c3e9/get_racing_meetings_by_date' \
  -H 'X-API-Key: $PARSE_API_KEY'
Python SDK · recommended

Typed, relational, agent-ready

A generated client with real types, enums, and the links between objects — the structure a flat JSON response can't carry. Autocompletes in your editor and reads cleanly to coding agents.

  • Fully typed · autocompletes
  • Objects link to objects
  • Typed errors & pagination

Typed Python client. Set up the SDK in your uv project, then pull this API’s typed client:

uv add parse-sdk
uv run parse init
uv run parse add --marketplace tab-com-au-api

uv run parse add --marketplace pulls a pinned snapshot of this canonical API — it won’t change underneath you. To customize it, subscribe and swap to your own copy.

"""
TAB Australia API Client
Horse racing data, sports betting odds, and account information from TAB.com.au

Get your API key from: https://parse.bot/settings
"""

import os
import requests
from typing import Optional, Any, Dict, List
from datetime import datetime


class ParseClient:
    """Client for interacting with the TAB Australia API via Parse."""

    def __init__(self, api_key: Optional[str] = None):
        """
        Initialize the Parse API client.

        Args:
            api_key: API key for authentication. If not provided, reads from PARSE_API_KEY env var.
        """
        self.base_url = "https://api.parse.bot"
        self.scraper_id = "38bc6ea2-d123-477f-bf57-9b9312f634d8"
        self.api_key = api_key or os.getenv("PARSE_API_KEY")
        self.session_id: Optional[str] = None
        self.encryption_key: Optional[str] = None

        if not self.api_key:
            raise ValueError("API key must be provided or set as PARSE_API_KEY environment variable")

    def _call(
        self,
        endpoint: str,
        method: str = "POST",
        **params
    ) -> Dict[str, Any]:
        """
        Make an API call to the Parse scraper.

        Args:
            endpoint: The endpoint name (e.g., "get_racing_meetings_by_date")
            method: HTTP method ("GET" or "POST")
            **params: Parameters to pass to the endpoint

        Returns:
            Response data as a dictionary

        Raises:
            requests.exceptions.RequestException: If the API call fails
        """
        url = f"{self.base_url}/scraper/{self.scraper_id}/{endpoint}"
        headers = {
            "X-API-Key": self.api_key,
            "Content-Type": "application/json"
        }

        # Add session info if available
        if self.session_id:
            params["sessionId"] = self.session_id
        if self.encryption_key:
            params["encryptionKey"] = self.encryption_key

        try:
            if method == "GET":
                response = requests.get(url, headers=headers, params=params)
            elif method == "POST":
                response = requests.post(url, headers=headers, json=params)
            else:
                raise ValueError(f"Unsupported HTTP method: {method}")

            response.raise_for_status()
            return response.json()
        except requests.exceptions.RequestException as e:
            print(f"API Error calling {endpoint}: {e}")
            raise

    def login(self, username: str, password: str) -> Dict[str, Any]:
        """
        Authenticate a user to obtain a session token.

        Args:
            username: Account username
            password: Account password

        Returns:
            Response containing accessToken and user info
        """
        response = self._call(
            "login",
            method="POST",
            username=username,
            password=password
        )

        # Store session info for subsequent calls
        if "accessToken" in response:
            self.session_id = response.get("accessToken")

        return response

    def get_racing_meetings_by_date(
        self,
        date: Optional[str] = None,
        jurisdiction: str = "NSW"
    ) -> List[Dict[str, Any]]:
        """
        Retrieve all racing meetings for a given date.

        Args:
            date: Date in YYYY-MM-DD format. Defaults to today.
            jurisdiction: State jurisdiction code (NSW, VIC, QLD, etc.)

        Returns:
            List of meeting objects
        """
        params = {"jurisdiction": jurisdiction}
        if date:
            params["date"] = date

        response = self._call(
            "get_racing_meetings_by_date",
            method="GET",
            **params
        )
        return response.get("meetings", [])

    def get_next_to_jump_races(self) -> List[Dict[str, Any]]:
        """
        Retrieve the next races to jump across all venues and race types.

        Returns:
            List of race objects with startTime and raceName
        """
        response = self._call(
            "get_next_to_jump_races",
            method="GET"
        )
        return response.get("races", [])

    def get_race_card(
        self,
        date: str,
        venue_code: str,
        venue: str,
        race_number: int,
        race_type: str
    ) -> Dict[str, Any]:
        """
        Retrieve full race card/details for a specific race.

        Args:
            date: Race date (YYYY-MM-DD)
            venue_code: Venue code
            venue: Venue name slug
            race_number: Race number
            race_type: Race type (thoroughbred, harness, greyhound)

        Returns:
            Race card with raceName and runners list
        """
        return self._call(
            "get_race_card",
            method="GET",
            date=date,
            venue_code=venue_code,
            venue=venue,
            race_number=race_number,
            race_type=race_type
        )

    def get_race_fixed_odds(
        self,
        date: str,
        venue_code: str,
        venue: str,
        race_number: int,
        race_type: str
    ) -> List[Dict[str, Any]]:
        """
        Retrieve current fixed odds for a specific race.

        Args:
            date: Race date (YYYY-MM-DD)
            venue_code: Venue code
            venue: Venue name slug
            race_number: Race number
            race_type: Race type

        Returns:
            List of fixed odds with runnerNumber, winPrice, and placePrice
        """
        response = self._call(
            "get_race_fixed_odds",
            method="GET",
            date=date,
            venue_code=venue_code,
            venue=venue,
            race_number=race_number,
            race_type=race_type
        )
        return response.get("fixedOdds", [])

    def get_race_results(
        self,
        date: str,
        venue_code: str,
        venue: str,
        race_number: int,
        race_type: str
    ) -> Dict[str, Any]:
        """
        Retrieve final results for a completed race.

        Args:
            date: Race date (YYYY-MM-DD)
            venue_code: Venue code
            venue: Venue name slug
            race_number: Race number
            race_type: Race type

        Returns:
            Results with finishing positions and dividends
        """
        return self._call(
            "get_race_results",
            method="GET",
            date=date,
            venue_code=venue_code,
            venue=venue,
            race_number=race_number,
            race_type=race_type
        )

    def get_account_balance(self) -> float:
        """
        Retrieve the authenticated user's account balance.
        Requires prior login.

        Returns:
            Available balance as a float
        """
        response = self._call(
            "get_account_balance",
            method="GET"
        )
        return response.get("availableBalance", 0.0)


if __name__ == "__main__":
    # Initialize client with API key from environment
    client = ParseClient()

    print("=" * 60)
    print("TAB Australia Racing API - Practical Workflow Example")
    print("=" * 60)

    # Step 1: Check upcoming races
    print("\n[1] Getting next races to jump...")
    next_races = client.get_next_to_jump_races()

    if next_races:
        upcoming_race = next_races[0]
        print(f"   Next race: {upcoming_race.get('raceName')} at {upcoming_race.get('startTime')}")

    # Step 2: Get today's meetings
    print("\n[2] Getting today's racing meetings (NSW)...")
    today = datetime.now().strftime("%Y-%m-%d")
    meetings = client.get_racing_meetings_by_date(date=today, jurisdiction="NSW")

    if meetings:
        print(f"   Found {len(meetings)} meetings:")
        for meeting in meetings[:3]:  # Show first 3
            print(f"   - {meeting.get('meetingName')} ({meeting.get('venueCode')})")

        # Step 3: Get race card for first meeting
        if meetings:
            first_meeting = meetings[0]
            venue_code = first_meeting.get("venueCode", "R")
            venue_slug = first_meeting.get("meetingName", "RANDWICK").lower()

            print(f"\n[3] Getting race card for Race 1 at {first_meeting.get('meetingName')}...")
            try:
                race_card = client.get_race_card(
                    date=today,
                    venue_code=venue_code,
                    venue=venue_slug,
                    race_number=1,
                    race_type="R"
                )

                race_name = race_card.get("raceName", "Race 1")
                runners = race_card.get("runners", [])
                print(f"   Race: {race_name}")
                print(f"   Runners ({len(runners)}):")
                for runner in runners[:5]:  # Show first 5 runners
                    print(f"     - #{runner.get('number')}: {runner.get('name')}")

                # Step 4: Get odds for this race
                print(f"\n[4] Getting fixed odds for Race 1...")
                odds = client.get_race_fixed_odds(
                    date=today,
                    venue_code=venue_code,
                    venue=venue_slug,
                    race_number=1,
                    race_type="R"
                )

                print(f"   Found {len(odds)} odds entries:")
                for odd in odds[:3]:  # Show first 3
                    runner_num = odd.get("runnerNumber")
                    win_price = odd.get("winPrice")
                    place_price = odd.get("placePrice")
                    print(f"     - Runner {runner_num}: Win ${win_price:.2f}, Place ${place_price:.2f}")

            except Exception as e:
                print(f"   (Unable to fetch detailed race info: {e})")

    # Step 5: Authentication flow (commented out without valid credentials)
    print("\n[5] Authentication Example (requires valid credentials):")
    print("   To access account balance, login with:")
    print("   >>> client.login(username='your_username', password='your_password')")
    print("   >>> balance = client.get_account_balance()")
    print("   >>> print(f'Account Balance: ${balance:.2f}')")

    print("\n" + "=" * 60)
    print("Workflow completed successfully!")
    print("=" * 60)
All endpoints · 5 totalmissing one? ·

Retrieve all racing meetings for a given date across all race types.

Input
ParamTypeDescription
datestringDate in YYYY-MM-DD format. Defaults to today.
jurisdictionstringState jurisdiction code (NSW, VIC, QLD, etc.)
Response
{
  "type": "object",
  "fields": {
    "meetings": "array"
  },
  "sample": {
    "meetings": [
      {
        "raceType": "R",
        "venueCode": "R",
        "meetingName": "RANDWICK"
      }
    ]
  }
}

About the TAB API

Racing Meetings and Next to Jump

get_racing_meetings_by_date returns a meetings array for any date in YYYY-MM-DD format, optionally filtered by a state jurisdiction code (NSW, VIC, QLD, etc.). Omit the date parameter and it defaults to today. get_next_to_jump_races takes no inputs and returns a races array reflecting the current queue of imminent races across all venues — useful for real-time dashboards or alert systems that need to react to race start times without polling a full meeting list.

Race Cards and Fixed Odds

Both get_race_card and get_race_fixed_odds require four identifying parameters — date, venue (as a name slug), venue_code, and race_number — plus a race_type of thoroughbred, harness, or greyhound. get_race_card returns a runners array and a raceName string, giving you the full field for a specific race. get_race_fixed_odds returns a fixedOdds array reflecting current TAB-listed odds for each runner in that race.

Race Results

get_race_results uses the same five-parameter signature and returns a results array alongside a dividends object once a race is complete. The dividends object covers payout data for the applicable bet types for that race. This endpoint is only meaningful after a race has been run — querying a future race will not return result data.

Coverage Notes

The API covers the three race types TAB supports: thoroughbred, harness, and greyhound racing. All endpoints that target a specific race share a consistent parameter set, so venue and date references are interchangeable across the race card, odds, and results calls for the same event.

Reliability & maintenance

The TAB API is a managed, monitored endpoint for tab.com.au — not a raw scraper you maintain. Every endpoint is automatically health-checked on a schedule, and when tab.com.au changes and a check fails, the API is automatically queued for repair and re-verified. It is built to keep working as the site underneath it changes.

This isn't an official tab.com.au API — it's an independent, maintained REST wrapper over public data. Where the source has no official API (or only a limited one), Parse gives you a stable contract over a source that never promised one, and keeps it current. Need a new endpoint or field? You can revise it yourself in plain English and the agent rebuilds it against the live site in minutes — contributing the change back to the shared API is free.

Will this API break when the source site changes?+
It's built not to. Every endpoint is health-checked on a schedule with automated test probes. When the source site changes and a check fails, the API is automatically queued for repair and re-verified — that's the self-healing layer. Each API page shows when its endpoints were last verified. And because marketplace APIs are shared, any fix reaches everyone using it.
Is this an official API from the source site?+
No — Parse APIs are independent, managed REST wrappers over publicly available data. That is the point: where a site has no official API (or only a limited one), Parse gives you a maintained, monitored endpoint for that data and keeps it working as the site changes — so you get a stable contract over a source that never promised one.
Can I fix or extend this API myself if I need a new endpoint or field?+
Yes — and you don't have to wait on us. This API was generated by the Parse agent, which stays attached. Describe the change in plain English ("add an endpoint that returns reviews", "fix the price field") in the revise box on the API page or via the revise_api MCP tool, and the agent rebuilds it against the live site in minutes. Contributing the change back to the public API is free.
What happens if I call an endpoint that has an issue?+
Errors are machine-readable: a bad call returns a clean status with the list of available endpoints and a repair hint, so an agent (or you) can recover or trigger a fix instead of failing silently. Confirmed failures feed the automatic repair queue.
Common use cases
  • Build a race-day dashboard that lists all Australian meetings by state using get_racing_meetings_by_date filtered by jurisdiction code
  • Power a 'next to jump' widget on a betting or sports news site using the get_next_to_jump_races endpoint
  • Display full race fields including runner names by fetching the runners array from get_race_card
  • Track current fixed odds movements for a specific race by polling get_race_fixed_odds on a schedule
  • Record historical race outcomes and dividends by querying get_race_results after each race completes
  • Build a multi-race comparison tool for greyhound or harness races by iterating race numbers across a venue
  • Alert users when a monitored runner's odds change by comparing successive fixedOdds array responses
Pricing & limitsSee full pricing →
TierPriceCredits/monthRate limit
Free$0/mo2005 req/min
Hobby$30/mo1,00020 req/min
Developer$100/mo5,000100 req/min
Team$300/mo20,000300 req/min
Company$1,000/mo100,000500 req/min

Each endpoint has a fixed posted price per successful call — most fall between 1 and 10 credits — shown on this API's page before you run it. Exceeding the rate limit returns a 429 response. Authenticate with the X-API-Key header.

Frequently asked questions
Does TAB.com.au have an official developer API?+
TAB does not publish a public developer API or documented REST interface for third-party use. This Parse API provides structured access to TAB racing and odds data without requiring any official partnership or account.
What does get_race_fixed_odds return, and how current is the data?+
It returns a fixedOdds array for the specified race, reflecting TAB's current fixed-price odds for each runner. Odds on TAB can change up to race start, so the freshness of the data depends on when you call the endpoint. For live odds tracking, periodic polling is the appropriate approach.
Does the API cover sports betting markets, not just racing?+
The current endpoints cover racing only: meetings, race cards, fixed odds, and results for thoroughbred, harness, and greyhound races. TAB also offers sports betting markets on its site. You can fork this API on Parse and revise it to add an endpoint targeting TAB's sports betting data.
Can I retrieve results and dividends for exotic bets like trifectas or first fours?+
get_race_results returns a dividends object that reflects payout data for the applicable bet types for that race. The specific bet types included in the dividends object depend on what TAB settles for each race. If you need to filter or expand dividend coverage beyond what the current endpoint returns, you can fork the API on Parse and revise the endpoint logic.
Do I need both venue and venue_code to query a specific race?+
Yes. get_race_card, get_race_fixed_odds, and get_race_results all require both the venue slug and the venue_code alongside the date, race_type, and race_number. You can obtain the venue slug and code from the meetings array returned by get_racing_meetings_by_date.
Page content last updated . Spec covers 5 endpoints from tab.com.au.
Related APIs in SportsSee all →
racingtv.com API
Access detailed information about UK and international horse racing meetings, including complete racecards, runner details, Timeform analysis, pace bias data, and draw commentary. Plan your racing strategy or stay informed on upcoming races with comprehensive meeting schedules and expert insights all in one place.
neds.com.au API
Get up-to-date horse racing information from Neds, including upcoming races, event details, and past results. View which races are next to jump and access comprehensive race data all in one place.
racingpost.com API
Access comprehensive horse racing data from Racing Post, including daily racecards, meeting schedules, race results, and detailed horse profiles with form history, stats, and pedigree.
racing.hkjc.com API
Access comprehensive horse racing data from the Hong Kong Jockey Club. Retrieve race results, detailed horse profiles including pedigree and form records, jockey and trainer season rankings, upcoming race meeting fixtures, and horse search by name.
attheraces.com API
Access comprehensive horse racing intelligence from At The Races, including detailed racecards, draw statistics, pace analysis, and form scan data to inform your betting decisions. Get all the performance metrics and positional data you need to analyze races and horses in one place.
timeform.com API
Access comprehensive horse racing information including today's and tomorrow's fixtures, detailed runner data with jockey and trainer information, and Timeform's expert ratings to help inform your betting decisions. Get real-time insights on top-rated horses and make smarter racing selections with professional-grade data at your fingertips.
atg.se API
Access comprehensive horse racing data from ATG.se, including race calendars, detailed race information, horse profiles, starting lineups, and results. Retrieve up-to-date information on races, horses, drivers, betting pools, and outcomes.
sportinglife API
Access comprehensive UK and Irish horse racing racecards from Sporting Life to view meeting schedules, race details, and detailed runner information with form analysis. Plan your betting strategy with up-to-date racecard data including horse forms and race conditions all in one place.