We extract event schedules, route profiles, ZwiftPower race results, and club leaderboards. Delivered as clean JSON, CSV, or Parquet to S3, BigQuery, or Snowflake on your cadence.
Structured, schema-consistent data across all major object types — delivered clean, typed, and ready to query.
Complete list of extractable fields for Events & Races objects from zwift.com. All fields typed and schema-versioned.
"event_id": "349102", "title": "Tour de Zwift Stage 2", "world": "Watopia", "distance_km": 42.5, "elevation_m": 342, "start_time": "2024-01-14T18:00:00Z", "category_enforcement": true, "registered_count": 1492
| # | event_id | title | world | route | distance_km | elevation_m |
|---|---|---|---|---|---|---|
| 1 | ||||||
| 2 | ||||||
| 3 |
Complete list of extractable fields for Routes & Worlds objects from zwift.com. All fields typed and schema-versioned.
"route_id": "watopia_figure_8", "name": "Figure 8", "world": "Watopia", "total_distance": 29.8, "total_elevation": 234, "badge_xp": 580, "difficulty_rating": 3.2, "leadin_distance": 0.2
| # | route_id | name | world | leadin_distance | total_distance | total_elevation |
|---|---|---|---|---|---|---|
| 1 | ||||||
| 2 | ||||||
| 3 |
Complete list of extractable fields for ZwiftPower Results objects from zwift.com. All fields typed and schema-versioned.
"zwptid": "849201", "rider_name": "J. Doe", "category": "B", "position": 14, "time_seconds": 3412, "wkg": 3.8, "avg_watts": 284, "avg_hr": 165
| # | zwptid | rider_name | category | position | time_seconds | gap_seconds |
|---|---|---|---|---|---|---|
| 1 | ||||||
| 2 | ||||||
| 3 |
Complete list of extractable fields for Segments objects from zwift.com. All fields typed and schema-versioned.
"segment_id": "alpe_du_zwift", "name": "Alpe du Zwift", "type": "KOM", "distance_m": 12200, "avg_gradient": 8.5, "record_time": 2014, "world": "Watopia", "max_gradient": 14.2
| # | segment_id | name | type | distance_m | avg_gradient | max_gradient |
|---|---|---|---|---|---|---|
| 1 | ||||||
| 2 | ||||||
| 3 |
Complete list of extractable fields for Clubs objects from zwift.com. All fields typed and schema-versioned.
"club_id": "99382", "name": "DIRT", "member_count": 14291, "public_status": true, "event_count": 42, "tags": "['racing', 'social']", "owner_name": "M. Smith", "created_at": "2018-04-12T00:00:00Z"
| # | club_id | name | description | member_count | public_status | event_count |
|---|---|---|---|---|---|---|
| 1 | ||||||
| 2 | ||||||
| 3 |
Our Zwift scraper handles the complex web of Zwift.com event listings and ZwiftPower race telemetry. We parse route parameters, categorical enforcement rules, and historical results with precision.
Scrape the full calendar of upcoming rides and races, including category limits and registered rider counts.
Extract distance, elevation gain, lead-in metrics, and badge XP for every defined route.
Pull race results, categorical upgrades, and 20-minute power metrics directly from ZwiftPower.
Track KOM, Sprint, and lap segment metrics across all worlds and map expansions.
Monitor active worlds and schedule changes to align with event planning.
Extract public club rosters, event histories, and membership counts.
Map frames, wheels, and aerodynamic ratings from public databases to rider profiles.
Track A/B/C/D pen limits and zFTP/zMAP thresholds for competitive integrity.
Poll event participant counts leading up to the start gun for accurate grid sizing.
Archive past event results for longitudinal rider analysis and team scouting.
Brief in. Clean data out.
Provide event filters, club IDs, or route targets. We design the extraction schema together.
We configure crawlers for Zwift APIs and ZwiftPower web interfaces, managing proxy rotation and session states.
Schema validation, null-rate checks on power metrics, and sample result sets before full launch.
JSON / CSV / Parquet pushed to your S3 bucket, BigQuery dataset, or Snowflake stage on agreed cadence.
Zwift data is split between the main event portal, the companion app API, and ZwiftPower. We unify these streams into a single structured schema.
Event metadata lives on Zwift.com, while detailed race telemetry lives on ZwiftPower. We map IDs across both platforms to deliver a unified record containing both the route topography and the final sprint watts.
Zwift limits request velocity on their public event schedules. We distribute polling across residential proxies to maintain high-frequency updates without triggering automated bans.
ZwiftPower relies heavily on client-side rendering for race results. We use full browser sessions to execute JavaScript, ensuring all power data and category modifications are captured accurately.
Zwift frequently updates their zFTP and zMAP logic. Our extraction schemas are versioned and monitored for field drift, ensuring your warehouse tables do not break when the platform changes its rules.
We hash race results and event schedules to detect modifications. Downstream pipelines only receive new events or updated rider placements, saving compute costs.
Teams analyse competitor w/kg, sprint timing, and historical race performance to build race strategies.
Track participant turnout, category distribution, and peak engagement times to optimise calendar slots.
Ingest race results to adjust athlete training zones and track fitness progression over the indoor season.
Correlate virtual frame and wheel choices with race outcomes in top-tier events to guide marketing.
Build independent leaderboards and route completion trackers for specific clubs or regional groups.
Analyse large scale human performance data across diverse demographics using historical race telemetry.
"Zwift generates millions of data points every hour, but extracting historical race telemetry requires navigating a maze of undocumented APIs and legacy web portals."
Most teams struggle to unify Zwift's modern event schedule with ZwiftPower's legacy result structures. DataFlirt manages the proxy rotation, session handling, and schema normalisation required to turn virtual cycling into structured, queryable warehouse tables.
Everything supported by our zwift.com scraper — rendered SPA elements, auth walls, rate-limit evasion and beyond.
Open-source tooling on proven cloud infra — no vendor lock-in, full observability.
Scrapy handles crawl orchestration, deduplication, and retry logic. Playwright handles JavaScript rendering, cookie sessions, and interaction flows. Combined via scrapy-playwright middleware.
We maintain pools of residential ISP proxies across multiple regions. Rotation happens per-request with sticky sessions where required. IP score monitoring prevents blacklisted pool contamination.
Pipelines run on AWS Lambda (burst) and ECS (sustained). Airflow handles scheduling, dependency management, and SLA alerting. All state stored in managed Postgres.
Data delivered to where your team already works — no new tooling required.
About zwift.com scraping, legality, and pipeline operations.
Ask us directly →Scraping publicly available event schedules and race results is generally permissible. DataFlirt targets only public, non-authenticated data. We do not extract private telemetry or violate user privacy settings. Clients should review Zwift's ToS and consult legal counsel for specific use cases.
Both. We merge event metadata from Zwift's primary schedule with the detailed race results and power metrics hosted on ZwiftPower.
No. Live rider coordinates and instantaneous power output require authenticated API access or UDP packet interception. We extract post-race results and aggregate metrics.
We can poll the event calendar at sub-15-minute intervals to capture late additions or rider registration surges prior to the start time.
Yes. We extract all public performance metrics from ZwiftPower race results, including 20-minute power, w/kg, and category enforcement thresholds.
Our packages start based on event volume or route coverage. Contact us with your specific data requirements for a scoped quote.
20-minute scoping call. Pilot dataset within the week. Production within two. From continuous event monitoring to historical race analysis. We scope, build, and operate the pipeline. Tell us what you need.