Skip to main content

py-uconnect

Async Python client for the FCA/Stellantis Uconnect cloud API, used by the official apps of Fiat, Jeep, Alfa Romeo, Maserati, Chrysler, Dodge and Ram to show the vehicle state and send remote commands.

It powers the Uconnect Home Assistant integration. Version 1.0 is an async rewrite. If you are upgrading from 0.x, see the migration guide in CHANGELOG.md.

Installation

pip install py-uconnect

Python 3.11 or newer is required. The only dependency is aiohttp.

Quick start

import asyncio

from py_uconnect import Client
from py_uconnect.brands import FIAT_EU


async def main() -> None:
    async with Client(
        "foo@bar.com", "very_secret", pin="1234", brand=FIAT_EU
    ) as client:
        vehicles = await client.refresh()

        for vehicle in vehicles.values():
            print(vehicle.to_json(indent=2))


asyncio.run(main())

Client logs in on the first request and renews the credentials before they expire. The PIN is only needed for remote commands and settings changes and can be None otherwise.

To reuse an existing aiohttp.ClientSession, such as Home Assistant's shared session, pass it as session=. A session passed in is not closed by the client:

client = Client(email, password, pin, FIAT_EU, session=session)

Brands

Pick the configuration matching the brand of the app you use and the region of your account from py_uconnect.brands (or BRANDS by name):

Brand Configurations
Fiat FIAT_EU, FIAT_US, FIAT_CANADA, FIAT_ASIA
Jeep JEEP_EU, JEEP_US, JEEP_ASIA
Alfa Romeo ALFA_ROMEO_EU, ALFA_ROMEO_US_CANADA, ALFA_ROMEO_ASIA
Maserati MASERATI_EU, MASERATI_US_CANADA, MASERATI_ASIA
Chrysler CHRYSLER_US, CHRYSLER_CANADA
Dodge DODGE_US
Ram RAM_US

Vehicle data

Client.refresh() loads the vehicles of the account into client.vehicles (a dict keyed by VIN) and returns it. Each Vehicle combines the vehicle list, the detailed status, the remote status and the last known location. Fields are None when the vehicle does not report them:

Group Fields
General vin, nickname, make, model, year, region, sdp, image_url, fuel_type, privacy_mode
Status ignition_on, odometer, days_to_service, distance_to_service, distance_to_empty, range_gas, range_total, battery_voltage, battery_state_of_charge, oil_level, fuel_low, fuel_amount (distances have a matching *_unit field)
EV plugged_in, ev_running, charging, charging_level, charging_level_preference, state_of_charge, time_to_fully_charge_l1/_l2/_l3, ev_head_seat, ev_cabin_cond, charge_schedules
Tyres wheel_<front/rear>_<left/right>_pressure, _pressure_unit, _pressure_warning
Doors, windows door_driver_locked, door_passenger_locked, door_rear_left_locked, door_rear_right_locked, trunk_locked, liftgate_locked, window_driver_closed, window_passenger_closed, window_rear_left_closed, window_rear_right_closed, sunroof_closed
Climate hvac_on, hvac_temperature, hvac_temperature_unit
Location location (latitude, longitude, altitude, bearing, is_approximate, updated)
Services enabled_services (all services that are capable and enabled), supported_commands (names of the commands they enable)
Timestamps timestamp_info, timestamp_status

The raw responses are kept in raw_list_item, raw_info, raw_remote_status and raw_location, in case you need a value that is not parsed. to_dict(raw=True) and to_json(raw=True) include them.

Not every vehicle supports every endpoint. If an endpoint fails with an API error, the vehicle is kept with the data that is available, including the status snapshot some vehicles have in the vehicle list. Authentication and connection errors are raised.

Remote commands

from py_uconnect.command import COMMAND_DOORS_LOCK

vehicle = client.vehicles[vin]
if vehicle.supports(COMMAND_DOORS_LOCK):
    # Send the command and wait for the result reported by the vehicle
    ok = await client.command_verify(vin, COMMAND_DOORS_LOCK)

    # Or just send it, and wait later if needed
    correlation_id = await client.command(vin, COMMAND_DOORS_LOCK)
    ok = await client.wait_for_operation(vin, correlation_id, timeout=60)

command_verify() and wait_for_operation() return True if the vehicle reports success and False if it reports failure. If there is no result within timeout seconds they raise CommandTimeoutError. The result is polled from the remote operation status endpoint and, because that endpoint is not available in every region, from the vehicle notifications.

Command Name Description
COMMAND_DOORS_LOCK / _UNLOCK RDL / RDU Lock / unlock the doors
COMMAND_ENGINE_ON / _OFF REON / REOFF Remote engine start / stop
COMMAND_LIGHTS_HORN HBLF Flash the lights and sound the horn
COMMAND_LIGHTS ROLIGHTS Flash the lights
COMMAND_TRUNK_LOCK / _UNLOCK ROTRUNKLOCK / ROTRUNKUNLOCK Lock / unlock the trunk
COMMAND_LIFTGATE_LOCK / _UNLOCK ROLIFTGATELOCK / ROLIFTGATEUNLOCK Lock / unlock the liftgate
COMMAND_PRECOND_ON / _OFF ROPRECOND / ROPRECOND_OFF EV cabin preconditioning on / off
COMMAND_HVAC_ON / _OFF ROHVACON / ROHVACOFF Climate control on / off
COMMAND_COMFORT_ON / _OFF ROCOMFORTON / ROCOMFORTOFF Comfort on / off (not sent by the current apps)
COMMAND_CABIN_VENTILATION ACV Cabin ventilation
COMMAND_CHARGE CNOW Start charging now
COMMAND_DEEP_REFRESH DEEPREFRESH Ask the vehicle to report a fresh EV status
COMMAND_REFRESH_LOCATION VF Ask the vehicle to report its location (VF_B is a variant)
COMMAND_CLEAR_PERSONAL_DATA ROCLRPERSDATA Clear the personal data stored in the head unit

Client.command() sends the variant of a command that fits the vehicle, like the official apps: START_CHARGE instead of CNOW for vehicles with the CNOW2 service, the v2 deep refresh for vehicles with DEEPREFRESH2, and preconditioning instead of engine start/stop for vehicles that only support that. If the API rejects a command with HTTP 400, 403 or 404 and it has a newer variant, the variant is tried as well.

Vehicles with the ROHVACTMP service accept a target temperature for the climate control:

from py_uconnect import TemperatureUnit, hvac_params
from py_uconnect.command import COMMAND_HVAC_ON

await client.command_verify(vin, COMMAND_HVAC_ON, hvac_params(21.5))
await client.command_verify(
    vin, COMMAND_HVAC_ON, hvac_params(70, TemperatureUnit.FAHRENHEIT)
)

EV charging

from py_uconnect import ChargingLevel

await client.set_charging_level_verify(vin, ChargingLevel.LEVEL_THREE)

# Disable the first schedule
schedules = client.vehicles[vin].charge_schedules
schedules[0]["enableScheduleType"] = False
await client.set_charge_schedules_verify(vin, schedules)

max_soc is only supported by vehicles with the CSETTING2 service. The schedule format depends on the vehicle's schedule service, see docs/API.md; the client picks the right endpoint.

Other endpoints

client.api is the low-level API client: one method per endpoint, returning the decoded JSON as-is. For example:

report = await client.api.get_vehicle_health_report(vin)
recalls = await client.api.get_recalls(vin)
trip = await client.api.get_last_trip(vin)
alerts = await client.api.get_drive_alerts(vin)
await client.api.send_destination(vin, 45.0703, 7.6869, "Office")
Area Methods
Vehicle list_vehicles, get_vehicle_info, get_remote_status, get_vehicle_location, get_vehicle_health_report, get_vehicle_image, get_vehicle_equipment, get_vehicle_preferences, get_stolen_vehicle_status, get_vehicle_subscription, set_vehicle_nickname
Maintenance get_maintenance_history, get_recommended_maintenance, get_recalls, dismiss_recalls
Notifications get_vehicle_notifications, get_account_notifications
Remote operations command, pin_auth, get_remote_operation_status, get_remote_operation_last_status, get_remote_climate_configuration, send_destination
EV set_charging_level, set_charge_schedules
Trips get_trips, get_last_trip, get_trip, get_trip_summary, get_trip_report_settings
Eco-coaching get_eco_coaching_profiles, get_eco_coaching_last_trip, get_eco_coaching_best_trip, get_eco_coaching_trips, get_eco_coaching_monthly, get_eco_coaching_daily, get_eco_coaching_suggestions, get_eco_coaching_history
Alerts get_drive_alerts, set_drive_alerts, get_theft_alarm_status, set_theft_alarm_notifications

Methods that change something require the PIN and return the correlation ID of the operation, which can be passed to client.wait_for_operation().

See docs/API.md for the endpoints behind them. Endpoints without a method can be called with client.api.request(). {uid} in the path is replaced with the account UID:

r = await client.api.request("GET", f"/v1/accounts/{{uid}}/vehicles/{vin}/vhr/")

Errors

All errors derive from py_uconnect.UconnectError:

Exception Raised when
AuthenticationError The login was rejected (wrong credentials, account problems)
PinAuthenticationError The PIN is missing or was rejected
APIError The API returned an unexpected status or response (status, url and body attributes)
UconnectConnectionError Network error or timeout
CommandError A command was not accepted
CommandTimeoutError No command result was reported in time

Logging

The library logs to the py_uconnect logger. At DEBUG level it logs the API responses, which include vehicle data and location.

logging.getLogger("py_uconnect").setLevel(logging.DEBUG)

Command line

export UCONNECT_BRAND=FIAT_EU UCONNECT_EMAIL=foo@bar.com UCONNECT_PASSWORD=very_secret

uconnect vehicles                       # vehicles and their state as JSON
uconnect get get_vehicle_health_report VIN
uconnect --pin 1234 command VIN RDL     # lock the doors and wait for the result
uconnect raw GET '/v1/accounts/{uid}/vehicles/VIN/vhr/'

python -m py_uconnect works the same. Run uconnect --help for all options.

Service delivery platform

North American vehicles report an sdp field naming the connected services provider: SXM (SiriusXM Guardian) or SPRINT (Uconnect Access). It is None in the other regions. The provider does not change the API: all vehicles of a region use the same endpoints.

PIN authentication depends on the provider: the library uses the sdp of the vehicle, as the apps do, so call refresh() (or api.list_vehicles()) before sending commands.

If a SiriusXM Guardian vehicle does not show up, the account may still be a legacy Mopar account. Log in once with the official app for your brand and complete the account migration if it asks you to, then use the same credentials with this library.

Development

python -m venv .venv && . .venv/bin/activate
pip install -e ".[dev]"
ruff check . && ruff format --check . && mypy && pytest

The tests use a fake HTTP session and don't need network access. To run a read-only smoke test against your own account:

UCONNECT_EMAIL=... UCONNECT_PASSWORD=... UCONNECT_BRAND=FIAT_EU pytest tests/live -v

Metadata

Release files for py-uconnect 1.0.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for py-uconnect 1.0.0
File Size Uploaded
py_uconnect-1.0.0.tar.gz 51.5 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for py-uconnect 1.0.0
File Interpreter ABI Platform
py_uconnect-1.0.0-py3-none-any.whl Python 3 none any Details

Total release size: 91.0 kB

Release files / py_uconnect-1.0.0.tar.gz

Download URL py_uconnect-1.0.0.tar.gz
Size 51.5 kB
Tags Source
SHA-256 checksum
How to use checksums
15a621fa6ba3df52543b1bf5f0a316196dc8ec54b28b9b1e1e08ce3a1eee7439
BLAKE2b-256 checksum
How to use checksums
dada919275c4b69f71b05ad29118f9fbe870d70879702adfa48985c3cda863ff
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 19, 2026.

Transparency log

Release files / py_uconnect-1.0.0-py3-none-any.whl

Download URL py_uconnect-1.0.0-py3-none-any.whl
Size 39.4 kB
Tags Python 3
SHA-256 checksum
How to use checksums
96ec25928a87320cb850276fee3d2ae91a3e81cbedc6c110a659cd8e7f455434
BLAKE2b-256 checksum
How to use checksums
03f05e66bae6c1be84498e626272ece0b8d5be71acd01ac9f34c02e22f025ad0
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 19, 2026.

Transparency log

Release history Release notifications | RSS feed

This release

1.0.0 This release

2 release files

0.4.6

2 release files

0.4.5

2 release files

0.4.4

2 release files

0.4.3

2 release files

0.4.2

2 release files

0.4.0

2 release files

0.3.11

2 release files

0.3.9

2 release files

0.3.8

2 release files

0.3.7

2 release files

0.3.5

2 release files

0.3.4

2 release files

0.3.3

2 release files

0.3.2

2 release files

0.3.1

2 release files

0.3.0

2 release files

0.2.6

2 release files

0.2.5

2 release files

0.2.4

2 release files

0.2.3

2 release files

0.2.1

2 release files

0.2.0

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page