Skip to main content

API Overview

The tif1 API is a modern Python library for Formula 1 data analysis, telemetry processing, and motorsport analytics. Performance is the primary focus of the design. tif1 is a drop-in replacement for fastf1 in most common use cases. Load times are faster than fastf1 (author-measured; see the Introduction benchmarks). The speed comes from async operations, multi-layer caching, parallel HTTP fetching, and an optional Polars backend. tif1 serves data scientists, motorsport engineers, application developers, and racing enthusiasts. These users can work efficiently with Formula 1 data at scale.

What Makes tif1 Different

tif1 stands apart from other F1 data libraries through several key innovations:
  • Performance: Every component, from HTTP fetching to DataFrame construction, is optimized for speed. Async operations run in parallel. Caching happens at multiple layers (memory + SQLite). The optional Polars backend gives memory-efficient processing for large datasets.
  • Production Architecture: tif1 is built for production use, not only for research. It includes circuit breakers, retry logic, connection pooling, and DNS-over-HTTPS support. Error handling is complete. Loading degrades gracefully when CDN sources fail.
  • Developer Experience: Type hints throughout the codebase enable IDE autocomplete and type checking. Clear error messages with structured context make debugging quick. Consistent naming conventions make the API predictable and easy to learn.
  • Flexible Data Access: Load only the data that the task needs. Skip telemetry for faster lap time analysis. Load everything for full session exploration. The API adapts to each use case.
  • Modern Python Practices: tif1 supports Python 3.11+. It uses structural pattern matching, improved type hints, and async/await patterns. The codebase follows strict linting rules (Ruff) and maintains high test coverage.

Design Philosophy

The tif1 API is built on a foundation of carefully considered design principles that guide every architectural decision and implementation detail:

Performance First

Performance is not just a feature—it is the core reason tif1 exists. Every component has been profiled, optimized, and benchmarked:
  • Async Operations: All network I/O uses async/await patterns with niquests, a modern fork of requests. This enables parallel fetching of multiple data sources at the same time. tif1 can fetch all data for a 20-driver race session in parallel.
  • Multi-Layer Caching: An in-memory LRU cache holds hot data. A SQLite-backed persistent cache holds all fetched data. Cache hits return data in microseconds rather than seconds. The cache is content-addressed and validates data integrity.
  • Parallel Fetching: When loading session data, tif1 fetches lap data, telemetry, weather, and race control messages in parallel. The fetches use asyncio task groups. This reduces total load time from ~10-15 seconds to ~2-3 seconds for uncached sessions.
  • Optional Polars Backend: The Polars backend serves large datasets, for example multiple seasons and comparative analysis. It provides 2-5x better memory efficiency and faster DataFrame operations than pandas. The backend is lazy-loaded and can be switched at runtime.
  • Optimized JSON Parsing: tif1 uses orjson (written in Rust) instead of Python’s stdlib json. This gives 2-3x faster JSON parsing. The speed matters when processing megabytes of telemetry data.
  • Connection Pooling: HTTP sessions use connection pooling to reuse TCP connections across requests. This reduces connection overhead by ~50-100ms per request.

Simplicity and Ergonomics

Complex operations should stay simple. The API hides complexity behind consistent interfaces:
  • Minimal Entry Points: Most users only need get_session() to start working with F1 data. Everything else is discoverable through the returned Session object via IDE autocomplete.
  • Sensible Defaults: All optional parameters have sensible defaults. get_session() loads all available data by default. Disable unneeded data sources for faster loading.
  • Fuzzy Matching: Event names support fuzzy matching—“spa”, “belgium”, “Belgian Grand Prix”, and “Spa-Francorchamps” all work. Session types accept both full names (“Qualifying”) and short codes (“Q”). This reduces friction and makes the API more forgiving.
  • Progressive Disclosure: Basic usage is simple, but advanced features are available when needed. Start with session.laps for quick analysis, then dive into driver.get_lap(n).get_telemetry() for detailed telemetry work.
  • Method Chaining: Where appropriate, methods return objects that support further operations, enabling natural workflows like session.get_driver("VER").get_fastest_lap().get_telemetry().

Predictability and Consistency

The API should be easy to learn and remember:
  • Consistent Naming: All methods follow clear patterns—get_* for retrieval operations, load_* for data loading, clear_* for cache operations. Attributes use snake_case, classes use PascalCase.
  • Clear Data Hierarchies: The object model mirrors F1’s structure: Session contains Driver objects, which contain Lap objects, which contain Telemetry data. This mental model matches how most users think about F1 data.
  • Complete Type Hints: Every public function and method includes complete type hints. An IDE can show the expected parameters and the return values. This reduces the need to consult documentation.
  • Structured Errors: Exceptions include structured context (not just error messages) for programmatic error handling. A DataNotFoundError includes the year, event, and session that were not found.

Compatibility

Existing fastf1 users should be able to migrate with minimal friction:
  • Drop-in Replacement: The core API (get_session(), Session.laps, Driver objects) matches fastf1’s interface. Most fastf1 code works with tif1 by just changing the import.
  • Compatibility Layer: The tif1.fastf1_compat module provides shims for fastf1-specific functions like set_log_level() and Cache.enable_cache().
  • DataFrame Compatibility: DataFrames returned by tif1 have the same column names and structure as fastf1. Existing analysis code does not need changes.
  • Migration Path: Both libraries can run side-by-side during migration. Validate the behavior of each piece of code, then move it to tif1.

Extensibility and Customization

Advanced users should be able to customize behavior:
  • Configuration System: Global configuration via get_config() tunes performance parameters (max workers, cache TTL, validation). The same call switches backends (pandas/polars). It also controls behavior (ultra cold start mode, DNS-over-HTTPS).
  • Modular Architecture: The library is split into focused modules (http_session, async_fetch, cache, cdn). Each module can be used independently or replaced with a custom implementation.
  • Backend Abstraction: A common interface abstracts the DataFrame backend. New backends (DuckDB, Arrow) can be added without changing user-facing code.
  • Cache Management: The user has full control over cache behavior. Clear specific sessions, or clear by date range. Inspect cache size, vacuum the database, or disable caching entirely for testing.
  • Retry and Circuit Breaker: Configurable retry logic uses exponential backoff. Circuit breaker patterns handle transient network failures gracefully.

Quick Start

Get started with tif1 in seconds. The library handles all the complexity of data fetching, parsing, caching, and DataFrame construction behind a simple, consistent interface:

What Happens Behind the Scenes

get_session() orchestrates a complex series of operations to deliver data quickly and reliably:
  1. Input Validation and Normalization
    • Validates the year is within supported range (2018-2026)
    • Performs fuzzy matching on event name against the schedule database
    • Normalizes session type (accepts “Race”, “R”, “race”, “RACE”, etc.)
    • Raises DataNotFoundError with helpful context if validation fails
  2. Schedule Lookup
    • Queries the embedded schedule database (JSON files in src/tif1/data/schedules/)
    • Retrieves event metadata: official name, location, date, session times
    • Determines available sessions for the event (standard vs sprint weekend format)
    • Validates the requested session exists for this event
  3. Cache Check (SQLite)
    • Computes content-addressed cache key from (year, event, session, data types)
    • Queries the SQLite cache database in tif1’s OS-dependent cache directory by default
    • Checks cache TTL (time-to-live) to determine if cached data is still fresh
    • If cache hit and data is fresh, deserializes DataFrames and returns immediately (microseconds)
    • If cache miss or stale data, proceeds to fetch from CDN
  4. CDN URL Construction
    • Builds URLs for all requested data sources (laps, telemetry, weather, messages)
    • Uses a three-source CDN chain (jsDelivr primary, Hugging Face buckets fallback, StaticDelivr backup) pointing to TracingInsights GitHub data repositories
    • Constructs fallback URLs in case primary CDN fails
    • Includes cache-busting parameters when needed
  5. Parallel Async Fetching
    • Creates async tasks for each data source using asyncio.TaskGroup
    • Fetches all data sources in parallel (not sequential) using niquests
    • Uses connection pooling to reuse TCP connections
    • Implements retry logic with exponential backoff for transient failures
    • Falls back to alternative CDN sources if primary fails
    • Typical fetch time: 2-3 seconds for all data sources in parallel
  6. JSON Parsing
    • Parses JSON responses using orjson (Rust-based, 2-3x faster than stdlib)
    • Validates JSON structure against expected schema
    • Raises InvalidDataError if data is corrupted or malformed
    • Extracts nested data structures (lap arrays, telemetry points, etc.)
  7. DataFrame Construction
    • Converts parsed JSON into pandas or Polars DataFrames based on config
    • Applies column renaming to match fastf1 conventions
    • Sets appropriate data types (float64 for times, int64 for lap numbers, category for compounds)
    • Reorders columns to standard layout
    • Adds computed columns (IsPersonalBest, TyreLife, etc.)
    • Handles missing data gracefully (NaN for missing telemetry, empty DataFrames for missing sessions)
  8. Data Validation (Optional)
    • If validate_data config is enabled, runs Pydantic validation on data structures
    • Checks for logical consistency (lap times > 0, sector times sum to lap time, etc.)
    • Validates driver codes against known driver list
    • Can be disabled for 10-15% performance improvement in production
  9. Cache Storage
    • Serializes DataFrames to efficient binary format (pickle or parquet)
    • Stores in SQLite database with metadata (timestamp, data types, size)
    • Compresses data to reduce storage (typical compression ratio: 3-5x)
    • Updates cache statistics (hit rate, total size, entry count)
  10. Object Construction
    • Creates Session object with all loaded data
    • Initializes Driver objects for each driver in the session
    • Sets up lazy-loading for telemetry data (loaded on first access)
    • Establishes relationships between objects (Session → Driver → Lap → Telemetry)
    • Returns fully-initialized Session object ready for analysis
All of this happens transparently in milliseconds for cached data. Fresh downloads with parallel async fetching take a few seconds. The user sees only a simple function call. It returns a ready-to-use Session object.

Performance Characteristics

Use this performance profile to optimize workflows:
  • Cache Hit (Warm): 1-5 milliseconds
    • Data loaded from SQLite cache
    • DataFrame deserialization from binary format
    • No network I/O
  • Cache Miss (Cold): 2-5 seconds
    • Parallel async fetching of all data sources
    • JSON parsing and DataFrame construction
    • Cache storage for future use
    • Dominated by network latency, not CPU
  • Partial Cache Hit: 500ms - 2 seconds
    • Some data sources cached, others fetched
    • Only missing data sources are fetched
    • Faster than full cold start
  • Ultra Cold Start Mode: 100-300 milliseconds
    • Optimized for single-query scenarios
    • Skips some cache checks and optimizations
    • Trades repeated-query performance for first-query speed
    • Enable with config.set("ultra_cold_start", True)
  • Polars Backend: 30-50% faster for large datasets
    • Better memory efficiency (2-5x less RAM)
    • Faster filtering and aggregation operations
    • Lazy evaluation for complex queries
    • Enable with config.set("lib", "polars")

Entry Points

The tif1 API exposes five primary entry points that serve as the foundation for all data access, configuration, and cache management. For most use cases, these functions are the only imports needed:

Detailed Entry Point Usage

get_session(year, event, session_type, **kwargs)

The primary entry point for loading Formula 1 session data. The function accepts multiple input formats. It also provides fine-grained control over what data gets loaded. Function Signature:
Basic Usage Examples:
Selective Data Loading: Control exactly what data gets loaded to optimize performance for each specific use case:
Advanced Usage:
Parameters Deep Dive:
  • year (int): Championship year from 2018 to 2026
    • 2018-2024: Complete historical data
    • 2025-2026: Partial data (as events occur)
    • Earlier years: Not supported (data format changed)
    • Future years: Will be supported as data becomes available
  • event (str): Event name with flexible matching
    • Official names: “Monaco Grand Prix”, “British Grand Prix”
    • Circuit names: “Silverstone”, “Spa-Francorchamps”
    • Location names: “Monaco”, “Belgium”, “Great Britain”
    • Partial matches: “monaco”, “silver”, “spa”
    • Case insensitive: “MONACO”, “Monaco”, “monaco” all work
    • Fuzzy matching uses Levenshtein distance with threshold of 0.7
  • session_type (str): Session type with multiple formats
    • Full names: “Practice 1”, “Practice 2”, “Practice 3”, “Qualifying”, “Sprint”, “Race”
    • Short codes: “FP1”, “FP2”, “FP3”, “Q”, “S”, “R”
    • Sprint weekends: “Sprint Qualifying” or “SQ”
    • Case insensitive: “race”, “RACE”, “Race” all work
    • Normalized internally to canonical form
  • laps (bool): Load lap timing data
    • Includes: lap times, sector times, tire compounds, tire life, positions, pit stops
    • Size: ~50-200 KB per session (compressed)
    • Load time: ~200-500ms (cold), <5ms (warm)
    • Required for: almost all analysis workflows
  • telemetry (bool): Load high-frequency telemetry
    • Includes: speed, RPM, throttle, brake, gear, DRS, position (X/Y/Z)
    • Sampling rate: ~10-20 Hz (10-20 samples per second)
    • Size: ~5-20 MB per session (compressed)
    • Load time: ~1-3 seconds (cold), ~10-50ms (warm)
    • Required for: detailed lap analysis, corner analysis, driving style comparison
    • Optional for: lap time analysis, strategy analysis
  • weather (bool): Load weather conditions
    • Includes: air temp, track temp, humidity, pressure, wind speed/direction, rainfall
    • Sampling rate: ~1 sample per minute
    • Size: ~5-10 KB per session
    • Load time: ~100-200ms (cold), <5ms (warm)
    • Required for: understanding tire performance, strategy decisions
    • Optional for: pure lap time analysis
  • messages (bool): Load race control messages
    • Includes: flags (yellow, red, green), safety cars, penalties, DRS status
    • Size: ~10-50 KB per session
    • Load time: ~100-200ms (cold), <5ms (warm)
    • Required for: understanding race incidents, strategy impacts
    • Optional for: qualifying analysis, practice analysis
  • backend (Literal[“pandas”, “polars”] | None): DataFrame backend
    • None: Use global config setting (default)
    • "pandas": Use pandas DataFrames (more compatible, more features)
    • "polars": Use Polars DataFrames (faster, more memory efficient)
    • Can be changed per-session without affecting global config
    • Polars requires polars package installed
  • force_reload (bool): Bypass cache
    • False: Use cache if available (default, recommended)
    • True: Always fetch from CDN, ignore cache
    • Useful for: debugging, getting latest data, cache corruption
    • Slower: adds 2-5 seconds to load time
Return Value: Returns a Session object with the following key attributes and methods:
Exception Handling:
Performance Tips:
  1. Load only the needed data: Disable unused data sources
  2. Use cache effectively: Do not use force_reload unless necessary
  3. Consider Polars for large datasets: 2-5x better memory efficiency
  4. Batch load sessions: Use async methods for parallel loading

get_events(year, **kwargs)

Retrieve the complete event schedule for a championship year. The schedule includes all Grand Prix events with metadata, dates, locations, and session structures. Function Signature:
Basic Usage:
Filtering and Analysis:
Session Structure Analysis:
DataFrame Columns Explained:
  • RoundNumber (int): Sequential round number in championship (1-24)
  • EventName (str): Short event name (for example, “Monaco Grand Prix”)
  • OfficialEventName (str): Full official name (for example, “Formula 1 Grand Prix de Monaco 2024”)
  • Location (str): Circuit location/city (for example, “Monte Carlo”)
  • Country (str): ISO country code (for example, “MC” for Monaco)
  • EventDate (str/datetime): Date of main race
  • EventFormat (str): “standard” or “sprint”
  • Session1-5 (str): Session names (“Practice 1”, “Qualifying”, “Race”, etc.)
  • Session1-5Date (str): Local date/time for each session
  • Session1-5DateUtc (str): UTC date/time for each session
  • F1ApiSupport (bool): Whether F1 official API supports this event
Use Cases:
Performance Notes:
  • Schedule data is embedded in the package (no network I/O)
  • Load time: <1ms (reading from JSON files)
  • Data size: ~10-20 KB per year
  • No caching needed (always instant)
See Events API for complete documentation.

get_sessions(year, event)

List all available sessions for a specific event, accounting for standard vs sprint weekend formats. Function Signature:
Usage Examples:
Use Cases:
  • Validate session existence before loading
  • Build UI dropdowns for session selection
  • Iterate through all sessions in an event
  • Handle standard vs sprint weekend differences
See Events API for complete documentation.

get_config()

Access global configuration singleton:
See Config API for all available settings.

get_cache()

Manage the SQLite-backed cache:
See Cache API for complete cache management.

Core Objects

The tif1 API is built around a clear object hierarchy that mirrors the structure of Formula 1 data. Understanding this hierarchy is key to effective use of the library.

Primary Objects

These are the main objects that tif1 users interact with:

Session

The Session object represents an entire Formula 1 session (Practice, Qualifying, Sprint, or Race). It is the primary container for all session data. Key Attributes:
  • session.laps - All lap timing data from all drivers as a DataFrame
  • session.weather - Weather conditions throughout the session
  • session.race_control_messages - Official race control messages and flags
  • session.results - Final classification and session results
  • session.circuit_info - Circuit metadata (length, corners, location)
  • session.drivers - List of driver codes (for example, [‘VER’, ‘HAM’, ‘LEC’])
  • session.session_info - Session metadata (date, time, type)
Key Methods:
  • get_driver(code) - Get a Driver object for a specific driver
  • get_fastest_laps(by_driver=False) - Get fastest lap(s) from the session
  • get_laps_by_driver(code) - Get all laps for a specific driver
  • load() - Explicitly load data (usually called automatically)
Example:
See Session API for complete documentation.

Driver

The Driver object represents a specific driver within a session and provides convenient access to driver-specific data and operations. Key Attributes:
  • driver.code - Three-letter driver code (for example, ‘VER’)
  • driver.name - Full driver name (for example, ‘Max Verstappen’)
  • driver.team - Team name (for example, ‘Red Bull Racing’)
  • driver.number - Racing number (for example, 33)
  • driver.laps - All laps completed by this driver as a DataFrame
  • driver.telemetry - Telemetry data for all laps (if loaded)
Key Methods:
  • get_lap(lap_number) - Get a specific lap by number
  • get_fastest_lap() - Get the driver’s fastest lap
  • get_fastest_lap_tel() - Get telemetry for the fastest lap
  • get_lap_telemetry(lap_number) - Get telemetry for a specific lap
  • get_stint_data() - Analyze tire stint performance
Example:
See Driver API for complete documentation.

Lap

The Lap object represents a single lap by a driver and provides access to high-frequency telemetry data for that specific lap. Key Attributes:
  • lap.lap_number - Lap number in the session
  • lap.lap_time - Total lap time in seconds
  • lap.sector_times - Individual sector times
  • lap.compound - Tire compound used
  • lap.telemetry - High-frequency telemetry DataFrame
Key Methods:
  • get_telemetry() - Load telemetry data for this lap
  • get_speed_trace() - Get speed data along the lap
  • get_throttle_trace() - Get throttle application data
  • compare_to(other_lap) - Compare telemetry with another lap
Example:
See Lap API for complete documentation.

Data Models

These objects represent structured data returned by the API:

Laps

A DataFrame containing lap timing data with rich filtering and analysis methods. Columns:
  • Driver - Driver code
  • LapNumber - Sequential lap number
  • LapTime - Total lap time (seconds)
  • Sector1Time, Sector2Time, Sector3Time - Sector times
  • Compound - Tire compound (SOFT, MEDIUM, HARD, INTERMEDIATE, WET)
  • TyreLife - Age of tires in laps
  • IsPersonalBest - Boolean flag for personal best lap
  • Position - Track position at lap completion
  • PitInTime, PitOutTime - Pit stop timing
  • TrackStatus - Track condition flags
Methods:
  • pick_driver(code) - Filter to specific driver
  • pick_fastest() - Get fastest lap
  • pick_compound(compound) - Filter by tire compound
  • pick_track_status(status) - Filter by track status
See Laps Model for complete documentation.

Telemetry

A DataFrame containing high-frequency telemetry data sampled at ~10-20 Hz. Columns:
  • Distance - Distance along track (meters)
  • Speed - Speed (km/h)
  • RPM - Engine RPM
  • Throttle - Throttle position (0-100%)
  • Brake - Brake pressure (boolean or 0-100%)
  • DRS - DRS status (0=closed, 1=open)
  • Gear - Current gear (1-8)
  • X, Y, Z - 3D position coordinates
Usage:
See Telemetry Model for complete documentation.

SessionResults

Final classification and results for the session. Attributes:
  • position - Final position
  • driver_code - Driver code
  • driver_name - Full name
  • team - Team name
  • points - Championship points awarded
  • status - Finish status (Finished, DNF, DNS, etc.)
  • time - Total race time or gap to leader
  • fastest_lap - Fastest lap time
  • fastest_lap_number - Lap number of fastest lap
See SessionResults Model for complete documentation.

CircuitInfo

Circuit metadata and track information. Attributes:
  • name - Circuit name
  • location - City/region
  • country - Country
  • length_km - Track length in kilometers
  • corners - Number of corners
  • drs_zones - Number of DRS zones
  • lap_record - Lap record time and holder
See CircuitInfo Model for complete documentation.

API Categories

Core data access

Essential APIs for loading and working with F1 data:
  • Core API - Session, Driver, Lap classes and data loading
  • Models - Data model classes and structures
  • Events - Event and session discovery
  • Schedule - Schedule validation and schema

Data Pipeline

Internal data transformation and fetching:
  • Async Fetch - Parallel HTTP fetching with niquests
  • HTTP - HTTP session and networking
  • HTTP Session - Connection pooling and DoH support
  • CDN - Multi-source CDN management with fallback

Configuration & Cache

Performance and reliability management:
  • Config - Global configuration management
  • Cache - SQLite-backed caching system
  • Retry - Circuit breaker and retry logic

Visualization & Tools

User-facing utilities:
  • Plotting - F1-themed visualization utilities
  • CLI - Command-line interface
  • Jupyter - Notebook integration and rich displays

Utilities & Helpers

Supporting functionality:
  • Utils - General utility functions
  • Utilities - Helper functions for configuration and logging
  • Core Utils - Internal utilities for DataFrame operations
  • Types - Type definitions and hints
  • Validation - Pydantic models and data validation
  • Fuzzy - Fuzzy string matching for event/session names

Compatibility & Errors

Integration and error handling:

Common Workflows

Load and explore session

Analyze driver performance

Parallel data loading

Configuration and Optimization


Error Handling

tif1 uses a hierarchy of specific exceptions. These exceptions help with common issues:

Exception Hierarchy

Common Exceptions

  • DataNotFoundError: The requested GP, year, or session does not exist
  • NetworkError: All CDN sources failed or timed out
  • InvalidDataError: The data fetched from the CDN was corrupted
  • DriverNotFoundError: The driver code provided is not in this session
  • LapNotFoundError: The requested lap number does not exist for this driver
  • CacheError: Cache operation failed
  • SessionNotLoadedError: Attempted to access data before loading session

Error handling example

See Exceptions API for complete documentation.

Performance Tips

  1. Use async methods for parallel loading: 5-10x faster than sequential
  2. Enable ultra-cold start for single queries: Minimal latency
  3. Use polars lib for large datasets: Better memory efficiency
  4. Disable validation in production: 10-15% performance boost
  5. Increase concurrency for bulk operations: Faster parallel fetching
See Best Practices for more optimization tips.

Type Hints

All public APIs include full type hints for better IDE support:
See Types API for complete type definitions.

Next Steps

  • Core API - Start with Session, Driver, and Lap classes
  • Tutorials - Learn through practical examples
  • Best Practices - Optimize analysis code
  • FAQ - Common questions and answers

Core API

Session, Driver, Lap

Models

Data models

Events

Event discovery

Examples

Code examples
Last modified on September 8, 2026