Migrating from MAVSDK-Python ​
The mavsdk package on PyPI is changing.
It used to be MAVSDK-Python: an asyncio wrapper that talks gRPC to a mavsdk_server process bundled inside the package. From MAVSDK v4, the mavsdk name refers instead to a native binding that calls the MAVSDK C++ library directly (via C), with no gRPC and no server process.
The two have different APIs. This page explains what to do about it.
The short version ​
| Before | From v4 | |
|---|---|---|
| gRPC wrapper | mavsdk | mavsdk-grpc, imported as mavsdk_grpc |
| Native binding | did not exist | mavsdk, imported as mavsdk |
The gRPC wrapper deliberately installs under a different import name from the native binding, so the two can be installed side by side without overwriting each other.
Which one do I want? ​
Keep the gRPC API, keep getting updates — switch to mavsdk-grpc. It continues to be developed, including releases tracking MAVSDK v4. Change your requirements and one import:
pip install mavsdk-grpcimport mavsdk_grpc as mavsdk # or: from mavsdk_grpc import SystemNothing else in your code needs to change.
Change nothing at all — pin the last release under the old name (e.g. in your requirements.txt)
mavsdk<4This keeps working indefinitely, but receives no further updates.
Move to the native binding — read on. It is worth it if you want to drop the grpcio dependency, avoid shipping and launching a mavsdk_server binary, or use the synchronous API.
What the native binding changes ​
Beyond the API itself:
- No
grpciodependency, and nomavsdk_serversubprocess. The package wraps the MAVSDK C++ library via the C wrapper directly. - Two interfaces.
mavsdkexposes a synchronous, callback-based API;mavsdk.asyncioexposes an asyncio API close in spirit to MAVSDK-Python. Both come from the same distribution — there is nothing extra to install. - Explicit system discovery. MAVSDK-Python hid connection and discovery behind
drone.connect(). The native binding separates connecting from discovering systems, which matters once more than one vehicle is involved. - Plugins are constructed, not attributes.
drone.action.arm()becomesAction(drone).arm(). - Support for multiple systems.
- Support for server side plugins. This allows implementations of things like cameras, or gimbals using plugins such as
CameraServerandGimbalServer.
API mapping ​
| MAVSDK-Python | Native binding (asyncio) |
|---|---|
System() | Mavsdk(Configuration.create_with_component_type(...)) |
await drone.connect(system_address=url) | await mavsdk.add_any_connection(url) |
implicit in connect() | drone = await mavsdk.first_autopilot(timeout_s) |
drone.action | ActionAsync(system) |
drone.telemetry | TelemetryAsync(system) |
drone.telemetry.position() | telemetry.subscribe_position() |
except ActionError as e: e._result.result | except ActionError as e: e.result |
Side by side ​
Arming and taking off, before:
import asyncio
from mavsdk import System
async def run():
drone = System()
await drone.connect(system_address="udpin://0.0.0.0:14540")
async for state in drone.core.connection_state():
if state.is_connected:
break
await drone.action.arm()
await drone.action.takeoff()
await asyncio.sleep(5)
await drone.action.land()
asyncio.run(run())and after, using mavsdk.asyncio:
import asyncio
from mavsdk.asyncio import Mavsdk, Configuration, ComponentType
from mavsdk.asyncio.plugins.action import ActionAsync
async def run():
configuration = Configuration.create_with_component_type(
ComponentType.GROUND_STATION
)
mavsdk = Mavsdk(configuration)
await mavsdk.add_any_connection("udpin://0.0.0.0:14540")
drone = await mavsdk.first_autopilot(10.0)
if drone is None:
raise SystemExit("No autopilot found")
action = ActionAsync(drone)
await action.arm()
await action.takeoff()
await asyncio.sleep(5)
await action.land()
asyncio.run(run())The same thing synchronously, which has no MAVSDK-Python equivalent:
import time
from mavsdk import Mavsdk, Configuration, ComponentType
from mavsdk.plugins.action import Action
configuration = Configuration.create_with_component_type(ComponentType.GROUND_STATION)
mavsdk = Mavsdk(configuration)
mavsdk.add_any_connection("udpin://0.0.0.0:14540")
drone = mavsdk.first_autopilot(10.0)
if drone is None:
raise SystemExit("No autopilot found")
action = Action(drone)
action.arm()
action.takeoff()
time.sleep(5)
action.land()Getting help ​
If something here is wrong, unclear, or your use case isn't covered, please open an issue.

