atproto for Python: a generated AT Protocol SDK with an alpha stability warning
The AT Protocol (🦋 Bluesky) SDK for Python 🐍
At a glance
- What is it?
- MarshalX/atproto is a Python SDK for the AT Protocol behind Bluesky whose models and clients are generated from lexicons rather than hand written. It covers XRPC, Firehose, Jetstream, identity and crypto, and its own documentation labels it under construction with no version compatibility guarantee before 1.0.0.
- Who is it for?
- atproto suits Python developers who want typed AT Protocol access without hand writing models for every lexicon, and who need both a high level client and the full XRPC surface beneath it. It is the wrong choice for a production service that cannot absorb breaking changes, because the project states that compatibility between versions is not guaranteed until 1.0.0, and it is the wrong choice for a closed network that does not speak AT Protocol.
- Can I use it commercially?
- Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
- Is it still maintained?
- Yes. The repository received new commits within the last day.
- What is it written in?
- Mainly Python, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on October 23, 2026, and from our analysis. They are not legal advice.
Editorial analysis
The models are generated from lexicons, not written by hand
The AT Protocol SDK for Python describes itself as autogenerated from lexicons, well type hinted and documented, with sync and async clients. That single phrase sets the whole architecture. A lexicon in the AT Protocol is a schema describing a record type or a procedure, and the SDK reads those schemas and produces the corresponding models, queries and clients. The README states that all models, queries and procedures are generated automatically, and that the main focus is on the lexicons of atproto.com and bsky.app while there is no vendor lock on it. Point the code generator at your own lexicon schemas and it produces the same typed models and clients for them, which is what the custom lexicons feature and the `atp gen custom` command exist for. The practical value is that the type surface tracks the protocol. A new record type or a changed field arrives as an updated schema and a regeneration rather than as a patch to hand written models. The repository layout backs this up with a lexicons/ directory at the root and an update_lexicons.py script alongside it, plus a separate atproto_codegen package described as the code generator of models, clients and namespaces.
A high level client sits on top of the complete XRPC surface
The SDK is split into a convenience layer and a protocol layer, and the README is explicit about both. The high level client handles common tasks, and beneath it sits the complete XRPC surface, where XRPC is the request and response scheme the AT Protocol uses for its API methods. The quickstart example shows what the high level layer looks like in practice:
from atproto import Client, client_utils
def main():
client = Client()
profile = client.login('my-handle', 'my-password')
print('Welcome,', profile.display_name)
text = client_utils.TextBuilder().text('Hello World from ').link('Python SDK', 'https://atproto.blue')
post = client.send_post(text)
client.like(post.uri, post.cid)
if __name__ == '__main__':
main()The client logs in with a handle and password, reads the display name from the returned profile, builds rich text with a TextBuilder and sends a post. The stated benefit of type hints everywhere is that your IDE can move through the whole protocol. The package structure table lists what sits underneath, and it is worth reading as an architecture map. `atproto` holds import shortcuts to all the other packages and the documentation recommends using it. `atproto_client` is the XRPC client, data models and utilities such as a rich text helper. `atproto_core` covers NSID, AT URI schemes, CID, CAR files and DID documents, `atproto_crypto` handles multibase, signature verification and DID keys, `atproto_server` holds server side utilities such as JWT, and `atproto_lexicon` is the lexicon parser the generator itself depends on.
Installing is one pip command, and both client flavours behave the same
Installation is a single command with a stated minimum version:
pip install atprotoPython 3.9 or higher is required, and the package metadata narrows that to a range of 3.9 up to but not including 3.15, with classifiers listing 3.9 through 3.14. The sync and async clients are described as having identical method sets, which matters for how you structure an application. If you write against the sync client and later need concurrency, the method names and arguments carry over to the async version. The README shows both shapes, and the async example differs in three predictable ways: AsyncClient replaces Client, the awaits appear on the calls, and the entry point is asyncio.run(main()) instead of a direct call. The dependency list in the package metadata is worth scanning before you commit to it in a service, since it pulls in httpx for HTTP, pydantic for validation, websockets for streaming, cryptography, dnspython for handle resolution, libipld and zstandard for the data formats, and click for the command line entry points. The project also installs two console scripts, atp and atproto, both pointing at the same atproto_cli module.
Firehose, Jetstream and archive backfill cover the streaming side
Real-time data is a separate concern in this SDK, and it is split across three packages. atproto_firehose is the Firehose client and its models, atproto_jetstream is the Jetstream v2 client and its models, and atproto_subscription is described as the websocket subscription runtime sitting behind the streaming clients. The stated feature is real-time streaming over the Firehose or Jetstream, including archive backfill, which is the capability that separates consuming the live network from replaying history. The distinction between the two streaming systems matters when you choose a source. The Firehose is the original commit stream, while the documentation points to separate guide pages for Firehose and Jetstream, and the package table names Jetstream specifically as version 2. The examples directory shows how this is meant to be used in practice, with separate directories for firehose/ and jetstream/ alongside examples for home timelines, profile posts, sending posts, replies, reposts, images, video, rich text, deleting a post, liking and unliking, processing notifications, and advanced usage. Every runnable example is inlined in the documentation, which is a reasonable way to learn an SDK whose surface is mostly generated.
The alpha label and the compatibility warning are the first things to read
The README opens the SDK section with a warning that undercuts every other feature claim: under construction, and until the 1.0.0 release compatibility between versions is not guaranteed. The package metadata agrees, classifying the project as Development Status :: 3 - Alpha. This is the single most consequential fact for an adopter, and it changes how the release numbers should be read. The listed releases are v0.0.73 on 2026-10-17, v0.0.72 on 2026-09-10 and v0.0.71 on 2026-08-19, all sitting below 1.0.0, and a version numbered 0.0.x signals that the public interface may still move between patch releases. The project is clearly active, with the last push on 2026-10-17 and a release published the same day, and it uses semantic versioning with the minor position at zero. What that activity does not tell you is whether your code keeps working across an upgrade, and the documentation says plainly that it is not guaranteed. For an application you own end to end, that is manageable with a pinned version. For a library you publish and others depend on, it is a real cost, since you will be absorbing breaking changes for your own users until 1.0.0 lands.
Where atproto is the wrong tool for the job
There are clear boundaries to this SDK. The first is the protocol scope. atproto implements the AT Protocol, and the AT Protocol is a specific federated social network design built around lexicons, XRPC, DIDs and a Firehose. If you are building a service that does not speak that protocol, this library gives you a large surface area of code that will never be exercised. The second is the vocabulary of the data model. The SDK exposes identifiers and formats that exist because the protocol requires them, including NSID for namespaces, AT URI schemes, CID for content addressing, CAR files for archives, DAG-CBOR encoding, multibase encoding, DID documents and DID keys. Those are not general purpose utilities for Python, and pulling them in for an unrelated project means accepting cryptography, libipld and zstandard as transitive dependencies. The third limit is the one the version numbers already told you, which is the absence of a compatibility promise. The documentation also says explicitly that it is the SDK's documentation and not the protocol's, and points to atproto.com and bsky.network/docs for the protocol itself. If your requirement is a generic Bluesky client with a stable public API, a smaller library may serve you better. If your requirement is to implement the protocol's own semantics correctly, generating the clients is the argument for this one.
Editorial conclusion
atproto suits Python developers who want typed AT Protocol access without hand writing models for every lexicon, and who need both a high level client and the full XRPC surface beneath it. It is the wrong choice for a production service that cannot absorb breaking changes, because the project states that compatibility between versions is not guaranteed until 1.0.0, and it is the wrong choice for a closed network that does not speak AT Protocol. Verify first that the version you pin has the lexicon endpoints you need, that your Python falls inside the supported range of 3.9 to 3.14, and that the Firehose or Jetstream consumption pattern you plan matches what atproto_jetstream and atproto_subscription actually offer.
Frequently asked questions
How do I install the atproto Python SDK?
Run pip install atproto. Python 3.9 or higher is required, and the package metadata supports versions from 3.9 up to but not including 3.15.
Is the atproto Python SDK stable?
No. The README states it is under construction and that compatibility between versions is not guaranteed until the 1.0.0 release, and the package metadata classifies it as Development Status :: 3 - Alpha.
Does the atproto SDK support both sync and async clients?
Yes. The README describes sync and async clients with identical method sets, with AsyncClient and AsyncClient-based calls being the async counterpart of Client.
Can I generate clients for my own lexicons with atproto?
Yes. Point the code generator at your own lexicon schemas and it produces the same typed models and clients, using the atp gen custom command, with the atproto_cli package and the atp console script providing the command line.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/marshalx-atproto)Was this useful?