MotoGP Official Results & Standings Scraper avatar

MotoGP Official Results & Standings Scraper

Pricing

from $5.00 / 1,000 results

Go to Apify Store
MotoGP Official Results & Standings Scraper

MotoGP Official Results & Standings Scraper

Scrape official MotoGP/Moto2/Moto3 race results and championship standings, including historical seasons. No login required.

Pricing

from $5.00 / 1,000 results

Rating

0.0

(0)

Developer

Artsiom Kunitsyn

Artsiom Kunitsyn

Maintained by Community

Actor stats

0

Bookmarked

2

Total users

1

Monthly active users

2 days ago

Last modified

Categories

Share

motogp-scraper

Scrapes official MotoGP/Moto2/Moto3 race results and championship standings from motogp.com, via the site's own public results API โ€” no login required.

Contents

๐Ÿ”‘ Key features

  • Two entity types, one Actor. Set entityType to results (session-by-session finishing order) or standings (final championship standings).
  • Real historical depth. MotoGP's own API has real data for ~78 seasons.
  • Full session detail. Every result includes rider, team, constructor, time, gap to the leader, average speed, laps, points, and status โ€” for every session type (practice, qualifying, sprint, warm-up, race).
  • Real season-long rollups on every standings row โ€” wins, podiums, sprint wins, and sprint podiums, computed by the site's own API, not estimated.
  • seasonYear/category scoping โ€” crawl one season and/or one class instead of walking all history.
  • Delta mode built in. Every run classifies each item as new, changed, unchanged, or delisted against a persisted baseline.
  • maxItems defaults to 50 โ€” a fast preview, and what keeps an unconfigured run within Apify's automated 5-minute QA check. Clear maxItems (null) for a full run.

๐Ÿ“‹ Output

One dataset item per rider-per-session (results) or rider-per-season (standings) โ€” see .actor/dataset_schema.json for the full field list, or the Output tab's Results / Standings views for a readable table.

Example result record:

{
"source": "motogp",
"entity_type": "results",
"external_id": "8c630d23-bb85-4827-81d7-f9b2e4c9f342",
"url": "https://www.motogp.com/en/gp-results/2025/tha/motogp/rac/classification",
"season_year": 2025,
"category": "MotoGP",
"event_name": "GRAND PRIX OF THAILAND",
"circuit": "Chang International Circuit",
"country": "Thailand",
"session_type": "RAC",
"position": 1,
"rider_name": "Marc Marquez",
"rider_country": "Spain",
"team_name": "Ducati Lenovo Team",
"constructor_name": "Ducati",
"time": "39:37.244",
"average_speed": 179.3,
"total_laps": 26,
"points": 25,
"status": "INSTND",
"change_type": "new"
}

Example standing record:

{
"source": "motogp",
"entity_type": "standings",
"external_id": "c02e9026-9bba-4788-95cc-cab16b3283f6",
"url": "https://www.motogp.com/en/gp-results/2025/standings/motogp",
"season_year": 2025,
"category": "MotoGP",
"position": 1,
"rider_name": "Marc Marquez",
"team_name": "Ducati Lenovo Team",
"points": 545,
"race_wins": 11,
"podiums": 15,
"sprint_wins": 14,
"sprint_podiums": 16,
"change_type": "new"
}

๐Ÿ”ง Input

FieldTypeDefaultDescription
entityTypestringresultsresults or standings.
seasonYearintegerโ€”Scope to one season, e.g. 2025.
categorystringโ€”Scope to one class: motogp / moto2 / moto3.
maxItemsinteger50Stop after pushing this many items. Set to null for a full crawl.
modestringautoauto / full / incremental โ€” see Incremental mode.
concurrencyinteger20How many API calls to fetch in parallel โ€” validated at real sustained scale, see FAQ.
impersonatestringchromecurl_cffi TLS-impersonation target.
proxyConfigurationobjectoffApify Proxy config โ€” not needed; no anti-bot friction found.

๐Ÿ“ฅ Input examples

Default preview (50 results):

{ "entityType": "results" }

A full season's race results:

{ "entityType": "results", "seasonYear": 2025, "maxItems": null }

A season's final MotoGP standings only:

{ "entityType": "standings", "seasonYear": 2025, "category": "motogp", "maxItems": null }

๐Ÿ” Incremental (delta) mode

auto mode does a full scan the first time it runs for a given entityType/scope, then only pushes new/changed items on later runs. Only an uncapped, error-free run can detect delistings or update the baseline. In practice, results for a finished session/season rarely change โ€” this mostly matters for catching mid-weekend corrections or a season still in progress.

๐ŸŒ How to scrape motogp.com

motogp.com's own frontend calls a real, public REST API (api.pulselive.motogp.com/motogp/v1/results/...) with no authentication required โ€” this Actor replicates exactly those calls: seasons โ†’ events โ†’ categories โ†’ sessions โ†’ classification (or, for standings, seasons โ†’ categories โ†’ standings directly).

โ“ FAQ

Is there a rider/team directory? Not as a separate entity type โ€” motogp.com's own rider-profile pages are thin (bio text only, no structured career stats) and its team sitemap is empty. Every rider/team name you'd want is already on every results/standings row.

Does this need a proxy or API key? No โ€” the results API is fully open, no authentication or key required, and no anti-bot friction was found anywhere.

Why is concurrency capped at 20? That's the highest level validated so far โ€” a full season of results and the complete 78-season standings history were both crawled at concurrency 20 with zero errors and no rate-limit wall found.

A season's total points looks like a decimal (e.g. 207.5) โ€” is that a bug? No โ€” MotoGP awards half points for a race stopped early or shortened by weather, so both a single session's points and a season's summed total can be genuinely fractional. points is a real number, not always a whole one.