CarsXE

The carsxe package is the official CarsXE client for Python. It is async-first, built on httpx and pydantic v2. Requires Python 3.9 or later.

Installation

pip install carsxe
# uv add carsxe
# poetry add carsxe

Quick start

The client is an async context manager. Use async with so the underlying HTTP connection is closed when you're done.

import asyncio
import os
from carsxe import CarsXE

async def main():
    async with CarsXE(api_key=os.environ['CARSXE_API_KEY']) as client:
        result = await client.decode_vin('WBAFR7C57CC811956')
        print(result.data.make, result.data.model, result.data.year)

asyncio.run(main())

If you need to reuse the client across many calls (e.g. in a long-running server), instantiate it directly and call await client.close() when done instead.

client = CarsXE(api_key=os.environ['CARSXE_API_KEY'])

try:
    result = await client.decode_vin('WBAFR7C57CC811956')
finally:
    await client.close()

Methods

Core

MethodDescription
decode_vin(vin)Decode a 17-character VIN into full vehicle specifications
get_market_value(vin, *, mileage, state, condition)Retail, trade-in, and auction value estimates
get_recalls(*, vin, make, model, year)Open safety recalls — pass VIN or make/model/year
decode_plate(plate, state)VIN lookup from a license plate (50+ countries)
get_vehicle_history(vin)Title events, salvage, junk, and insurance records

Bulk recall batch

MethodDescription
submit_bulk_recall_batch(vins, *, csv, csv_url, webhook_url)Submit a batch of VINs
get_bulk_recall_batch_status(batch_id)Poll job status
get_bulk_recall_batch_results(batch_id)Retrieve completed results
get_bulk_recall_batch_download_url(batch_id)Get a CSV download URL

Error handling

By default the client raises CarsXEError on non-2xx responses. The exception carries status_code, code, and message.

from carsxe import CarsXE, CarsXEError
import os

async with CarsXE(api_key=os.environ['CARSXE_API_KEY']) as client:
    try:
        result = await client.decode_vin('WBAFR7C57CC811956')
    except CarsXEError as e:
        print(e.status_code, e.code, e.message)

Pass throw_on_error=False to suppress exceptions and inspect result.error instead:

client = CarsXE(api_key=os.environ['CARSXE_API_KEY'], throw_on_error=False)
result = await client.decode_vin('INVALID')
if result.error:
    print(result.error.message)

Best practices

Always use async with or call close(). The SDK uses an httpx.AsyncClient internally — leaving it open leaks connections.

Store your key in an environment variable.

# .env
CARSXE_API_KEY=your_key_here
import os
from dotenv import load_dotenv

load_dotenv()
api_key = os.environ['CARSXE_API_KEY']

Reuse the client. In a web server (FastAPI, Django async views), create the client once at startup and close it on shutdown — don't instantiate per-request.

# FastAPI example
from contextlib import asynccontextmanager
from fastapi import FastAPI
from carsxe import CarsXE

carsxe: CarsXE

@asynccontextmanager
async def lifespan(app: FastAPI):
    global carsxe
    carsxe = CarsXE(api_key=os.environ['CARSXE_API_KEY'])
    yield
    await carsxe.close()

app = FastAPI(lifespan=lifespan)