How OpenPilot Performs Vehicle Fingerprinting to Identify Unknown Car CAN Bus Configurations

OpenPilot identifies vehicles by capturing a deterministic fingerprint of CAN bus traffic—recording message IDs, bus numbers, and payload lengths—then matching this pattern against a static database of known configurations, with firmware queries resolving any remaining ambiguities.

OpenPilot, the open-source driving automation system maintained by commaai, relies on precise vehicle identification to interface with diverse automotive networks. Understanding how openpilot vehicle fingerprinting works is essential for developers porting new cars or debugging CAN bus integrations. The system employs a multi-stage identification process that analyzes raw CAN traffic during vehicle startup to determine the exact make and model.

Stage 1: Collecting Raw CAN Messages

When a route is replayed or a live vehicle connects, OpenPilot reads every CAN frame for a short window—typically a few seconds during the startup sequence. For each message, the system records the CAN ID, the bus it arrived on, and the payload length. This data is organized into a nested dictionary structure: fingerprint[bus][msg_id] = length.

The implementation resides in selfdrive/debug/fingerprint_from_route.py, which processes recorded drives, and selfdrive/debug/get_fingerprint.py, a minimal CLI tool for dumping fingerprints from live devices. During normal operation, the startup sequence in selfdrive/car/card.py triggers this collection and stores the result in CarParams.

Stage 2: Matching Against Known Fingerprints

The collected fingerprint dictionary is compared against the static database of known vehicle fingerprints located in the opendbc submodule at opendbc/car/fingerprints.py. Each entry in the FINGERPRINTS dictionary maps a specific car model name to the exact pattern of CAN IDs and lengths observed on its bus.

The matching algorithm first attempts an exact match. If no exact match is found, the system falls back to a fuzzy match that tolerates missing or extra messages. This fallback mechanism allows OpenPilot to recognize vehicles even when certain CAN messages are intermittently absent due to vehicle state variations.

Stage 3: Firmware-Based Refinement

Some vehicles share identical CAN traffic patterns, making pure CAN fingerprinting ambiguous. To resolve these conflicts, OpenPilot implements firmware (FW) fingerprinting by querying the vehicle's ECUs for firmware version strings (car_fw).

The tools/car_porting/auto_fingerprint.py script merges this firmware data with the CAN fingerprint to create a complete vehicle identifier. Additionally, the MIGRATION table in opendbc/car/fingerprints.py handles historic name changes and model identifier updates, ensuring backward compatibility with older vehicle definitions.

Handling Unknown Vehicle Configurations

If the collected CAN traffic does not match any entry in the fingerprint database, OpenPilot treats the vehicle as unknown. In this state, the system runs in a read-only "stock-mode" that prevents active control but logs the unmatched fingerprint for future analysis. These logged fingerprints are later reviewed for inclusion in the database to expand vehicle support.

Practical Code Examples

To obtain a CAN fingerprint from a replayed route:

from selfdrive.debug.fingerprint_from_route import get_fingerprint

lr = ...  # LogReader instance for the target route

fingerprint = get_fingerprint(lr)

# Returns: {bus: {msg_id: length}}

To match a fingerprint against the known vehicle database:

from opendbc.car.fingerprints import FINGERPRINTS, MIGRATION

def match_fingerprint(fp):
    for car, known_fp in FINGERPRINTS.items():
        if fp == known_fp:
            return car
    # Fallback fuzzy match logic would follow here

    return None

car_model = match_fingerprint(fingerprint)
if car_model:
    print(f"Detected car: {car_model}")
else:
    print("Unknown vehicle – logged for future support")

To generate a full fingerprint combining CAN data and firmware versions:

from tools.car_porting.auto_fingerprint import auto_fingerprint

fp, fw = auto_fingerprint(route_path="path_to_route")
print("CAN fingerprint:", fp)
print("FW fingerprint:", fw)

Summary

Frequently Asked Questions

What happens if OpenPilot cannot fingerprint my vehicle?

If no match is found in the fingerprint database, OpenPilot enters a read-only "stock-mode" that prevents active driving assistance but logs the unknown CAN traffic. This data is used by developers to add support for new vehicle models in future releases.

How does fuzzy fingerprinting differ from exact matching?

Exact matching requires every CAN ID and length in the collected fingerprint to match a database entry perfectly. Fuzzy matching tolerates discrepancies such as missing or extra messages, allowing vehicle identification even when certain ECUs are offline or transmit intermittently.

Where are vehicle fingerprints stored in the OpenPilot codebase?

Known fingerprints are stored in the external opendbc submodule at opendbc/car/fingerprints.py. This file contains the FINGERPRINTS dictionary mapping vehicle models to their CAN patterns, along with the MIGRATION table for handling identifier updates.

Can firmware fingerprinting alone identify a vehicle without CAN data?

No, firmware fingerprinting serves as a refinement layer rather than a primary identification method. The system first attempts CAN-based fingerprinting, then uses ECU firmware versions (car_fw) to resolve ambiguities when multiple vehicles share identical CAN bus configurations.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →