Claude API Rust SDK: Community Library Options
Is there an official Claude API Rust SDK?
No. Anthropic ships official SDKs for Python and TypeScript/JavaScript, but as of now there is no first-party Rust SDK for the Claude API. If you're building a Rust service that needs to call Claude, you have three realistic paths: use a community-maintained crate, write a thin HTTP client yourself against the REST API, or route through a gateway service that normalizes the API surface so your Rust code doesn't need to track Anthropic's wire format at all.
This guide covers all three, with working code for the "write it yourself" path since that's what most Rust teams end up doing anyway — the Claude Messages API is simple enough that a full SDK often isn't worth the dependency.
Community crates for Claude in Rust
Searching crates.io for "claude" or "anthropic" turns up a handful of community libraries at various stages of maintenance. Before pulling one in, check:
- Last publish date. Anthropic has changed response formats (extended thinking, tool_use blocks, usage fields) more than once. A crate untouched for a year may not parse current responses correctly.
- Streaming support. Many early community clients only implement non-streaming
messages.create. If you need SSE-based streaming, verify it explicitly in the crate's docs or source. - Tool use / function calling. Support for
tool_useandtool_resultcontent blocks is the feature most likely to be missing or partially implemented in smaller crates. - License and dependency footprint. Some wrap
reqwestandserde_jsondirectly (reasonable), others pull in large async runtimes you may not want.
Given how thin the Claude REST API actually is, many Rust developers conclude it's faster to write a 100-line module than to vet and maintain a third-party dependency that might lag behind Anthropic's changes.
Building your own minimal Claude client in Rust
The Messages API is a single POST endpoint with a JSON body and a few required headers. Here's a minimal client using reqwest and serde:
use serde::{Deserialize, Serialize};
use reqwest::Client;
#[derive(Serialize)]
struct Message {
role: String,
content: String,
}
#[derive(Serialize)]
struct MessagesRequest {
model: String,
max_tokens: u32,
messages: Vec<Message>,
}
#[derive(Deserialize, Debug)]
struct ContentBlock {
text: Option<String>,
}
#[derive(Deserialize, Debug)]
struct MessagesResponse {
content: Vec<ContentBlock>,
}
async fn send_message(api_key: &str, prompt: &str) -> anyhow::Result<String> {
let client = Client::new();
let body = MessagesRequest {
model: "claude-sonnet-4-5".to_string(),
max_tokens: 1024,
messages: vec![Message {
role: "user".to_string(),
content: prompt.to_string(),
}],
};
let resp = client
.post("https://api.anthropic.com/v1/messages")
.header("x-api-key", api_key)
.header("anthropic-version", "2023-06-01")
.json(&body)
.send()
.await?
.json::<MessagesResponse>()
.await?;
Ok(resp.content.first().and_then(|c| c.text.clone()).unwrap_or_default())
}
This covers the basic case. Adding streaming means parsing Server-Sent Events chunks yourself (look at the eventsource-stream or reqwest-eventsource crates), and tool use means extending ContentBlock with type, input, and id fields for tool_use blocks, plus a way to send tool_result blocks back in a follow-up request. None of this is hard, but it's the kind of boilerplate that a real SDK would normally absorb — and it's exactly the maintenance burden that makes "just use the HTTP API directly" a defensible long-term choice in Rust specifically, where the ecosystem around Claude is thinner than in Python or JS.
When a gateway is simpler than any SDK
If your actual goal is "call Claude from a Rust service reliably," you don't strictly need an Anthropic-flavored client at all — you need a stable HTTP endpoint with predictable auth, streaming, and usage metadata. That's a narrower problem than writing or vetting a full SDK.
SubToAPI sits in front of Claude and exposes it as a standard HTTPS API with application-level API keys (sub_live_...), SSE streaming, tool use, and per-key usage metadata in a dashboard. From Rust, it's the same shape of request as calling Anthropic directly — swap the base URL and header:
let resp = client
.post("https://api.subtoapi.app/v1/messages")
.header("Authorization", format!("Bearer {}", std::env::var("SUBTOAPI_KEY")?))
.json(&body)
.send()
.await?;
The advantage for a Rust-based team isn't a language-specific SDK — it's that you issue scoped sub_live_ keys per service or environment, see usage and cost per key in one dashboard, and manage team seats, instead of maintaining a Rust crate against a moving upstream spec. See /docs/quickstart for the full request format, /docs/messages for the Messages API reference, /docs/streaming for SSE handling, and /docs/tools for tool use. Plans start at €9/month on the Solo tier, with Team (€19/seat) and Scale (€49/seat) tiers for shared usage; see /pricing or start a free trial at /signup.
Practical recommendation
If your Rust project is small and you just need a few calls to Claude, write the ~100 lines of reqwest/serde code above and move on — it's less risk than a half-maintained crate. If you're running this in production across multiple services, prefer either a well-maintained crate with recent commits and explicit tool-use/streaming support, or a gateway that gives you keys, usage tracking, and a stable contract without being tied to any one language's SDK ecosystem.
FAQs
Is there an official Anthropic SDK for Rust? No. Anthropic currently publishes official SDKs for Python and TypeScript only. Rust developers rely on community crates or direct HTTP calls to the Messages API.
Can I just call the Claude API from Rust without any SDK? Yes. The Messages API is a single JSON POST endpoint, so a small reqwest + serde client (shown above) is often simpler and more maintainable than depending on a third-party crate.
What should I check before using a community Claude crate? Verify it supports streaming and tool_use/tool_result content blocks, check the last publish date against Anthropic's current API version, and confirm it's actively maintained before adding it to production code.