Skip to main content

Claude-API

An unofficial async Python client for the Claude.ai web interface.

Disclaimer: This library reverse-engineers Claude.ai's internal web API. It is not affiliated with or endorsed by Anthropic. Use responsibly.


Features

  • Multi-turn conversations — stateful ChatSession keeps threading across turns automatically
  • Streaming — yield tokens in real time as Claude writes them
  • Response styles — built-in presets (concise, explanatory, formal, learning) or a fully custom prompt; settable per-session or per-request
  • File attachments — attach local files or in-memory bytes to any message
  • File downloads — pull files generated by Claude's code interpreter
  • Model selection — any Claude model by enum or raw string
  • Session resumption — serialize and restore conversation state across processes
  • Async-first — built on aiohttp

Related projects

ChatAI Console

A full-featured self-hosted web UI for Claude, ChatWithAI.app and 1MinAI. Claude-API stems off of this

Features:

  • Multi-account management — Claude, ChatWithAI.app, and 1MinAI accounts in one place side-by-side
  • Real-time streaming with artifacts
  • File upload, download, and canvas preview panel
  • Google OAuth sign-in flow for Claude accounts
  • Quota tracking and usage history
  • Local conversation storage with pinning

Installation

Requires Python 3.10+.

pip install claude-webapi

Authentication

You can authenticate in either of two ways:

  1. Reuse an existing sessionKey cookie.
  2. Exchange a Google auth code from Claude's browser login flow with ClaudeClient.from_google_code(...).

If you already have a session cookie:

  1. Open claude.ai and log in.
  2. Press F12 → Application → Cookies → https://claude.ai.
  3. Copy the sessionKey cookie value.
  4. Your organization ID is in the lastActiveOrg cookie, or in the URL of any conversation.

Keep your sessionKey secret — it grants full access to your account.

If you want browser-based Google login instead of cookie reuse, pass the code returned by Claude's login flow:

client = await ClaudeClient.from_google_code(
    code="YOUR_GOOGLE_AUTH_CODE",
    arkose_session_token="YOUR_ARKOSE_SESSION_TOKEN",
)

The browser handles the OAuth sign-in; the library only exchanges the resulting code and boots a normal Claude session.


Quick start

import asyncio
from claude_webapi import ClaudeClient

async def main():
    async with ClaudeClient("sk-ant-…", "org-uuid-…") as client:
        r = await client.generate_content("What is the capital of France?")
        print(r.text)

asyncio.run(main())

organization_id is optional — the client will discover it automatically if omitted.


Usage

Single-turn generation

r = await client.generate_content("Explain quantum entanglement simply.")
print(r.text)

str(r) is equivalent to r.text.


Streaming

async for chunk in client.generate_content_stream("Write a haiku about Python."):
    print(chunk.text_delta, end="", flush=True)
print()

Multi-turn chat

chat = client.start_chat()

r1 = await chat.send_message("My name is Alice.")
r2 = await chat.send_message("What is my name?")   # → "Your name is Alice."

Streaming within a session:

async for chunk in chat.send_message_stream("Explain async/await in Python."):
    print(chunk.text_delta, end="", flush=True)
print()

r = await chat.send_message("Give me a one-line example.")   # context preserved

Response styles

Five built-in presets mirror Claude.ai's style selector:

Key Effect
"normal" Default Claude behaviour (default)
"concise" Shorter answers, less preamble
"explanatory" Teacher-style breakdowns with examples
"formal" Professional language, no contractions
"learning" Socratic / guided-discovery mode

You can also pass any arbitrary string as a custom style prompt, or a raw dict for full control over the personalized_styles payload.

Session-level style

All turns in the session use this style unless overridden per-request:

chat = client.start_chat(style="concise")

r1 = await chat.send_message("Explain Docker.")          # concise
r2 = await chat.send_message("Now explain Kubernetes.")  # concise

Per-request style override

Pass style= on any individual call — it takes precedence over the session default for that turn only:

chat = client.start_chat(style="concise")

r1 = await chat.send_message("Explain monads.")                        # concise
r2 = await chat.send_message("Now really dig into it.", style="explanatory")  # override
r3 = await chat.send_message("Summarise what we covered.")             # back to concise

Works on streaming turns too:

async for chunk in chat.send_message_stream("Write a poem.", style="formal"):
    print(chunk.text_delta, end="", flush=True)

Per-request style also works on the stateless methods:

r = await client.generate_content("Explain recursion.", style="learning")

async for chunk in client.generate_content_stream("Tell me a story.", style="formal"):
    print(chunk.text_delta, end="", flush=True)

Custom style prompt

chat = client.start_chat(style="Always reply in bullet points. Never use prose.")

Raw dict (full control)

chat = client.start_chat(style={
    "type": "custom",
    "key": "Pirate",
    "name": "Pirate",
    "nameKey": "pirate_style_name",
    "prompt": "Respond exclusively in pirate dialect. Arr.",
    "summary": "Pirate mode",
    "summaryKey": "pirate_style_summary",
    "isDefault": False,
})

File attachments

Pass local file paths to any message:

r = await client.generate_content(
    "Summarise this report.",
    files=["report.pdf", "chart.png"],
)

Upload raw bytes (file in memory):

chat = client.start_chat()
fid = await client.upload_file(
    chat.cid,
    data=b"col1,col2\n1,2\n3,4",
    filename="data.csv",
    mime_type="text/csv",
)
r = await chat.send_message("Analyse the CSV.", files=[fid])

Inline text attachments (no upload round-trip):

r = await client.generate_content(
    "Summarise the document below.",
    attachments=[{
        "extracted_content": "The quick brown fox…",
        "file_name": "notes.txt",
        "file_size": 1234,
        "file_type": "txt",
    }],
)

Download files from Claude's sandbox

chat = client.start_chat()
await chat.send_message("Generate the first 20 Fibonacci numbers and save as fib.csv.")
local = await client.download_file(chat.cid, "fib.csv", dest="./downloads")
print(f"Saved to: {local}")

Model selection

from claude_webapi.constants import Model

r = await client.generate_content("Hello!", model=Model.OPUS)

chat = client.start_chat(model=Model.HAIKU)   # session-level
r2 = await chat.send_message("Fast reply.", model=Model.SONNET)  # per-turn override

Available models:

Enum String
Model.SONNET claude-sonnet-4-6
Model.OPUS claude-opus-4-6
Model.HAIKU claude-haiku-4-5-20251001

Any model string not in the enum can be passed as a plain string.


Resume a previous conversation

import json

# First session
chat = client.start_chat()
await chat.send_message("The secret word is BANANA.")
with open("session.json", "w") as f:
    json.dump(chat.metadata, f)

# Later session
with open("session.json") as f:
    meta = json.load(f)

chat = client.start_chat(metadata=meta)
r = await chat.send_message("What was the secret word?")   # → BANANA

Delete a conversation

await chat.delete()
# or
await client.delete_conversation(chat.cid)

List conversations

convs = await client.list_conversations()
for c in convs[:5]:
    print(c["uuid"], c.get("name", "(unnamed)"))

Multiple reply candidates

r = await chat.send_message("Recommend a sci-fi novel.")
for i, c in enumerate(r.candidates):
    print(f"[{i}]", c.text[:120])

chat.choose_candidate(1)   # branch the conversation from candidate 1

Initialisation options

client = ClaudeClient(
    session_key="sk-ant-…",
    organization_id="…",   # optional, auto-discovered if omitted
    proxy="http://user:pass@host:port",  # optional HTTP proxy
)
await client.init(
    timeout=30,         # request timeout in seconds
    auto_close=True,    # close HTTP session after inactivity
    close_delay=300,    # inactivity threshold in seconds
)

Logging

from claude_webapi import set_log_level
set_log_level("DEBUG")   # DEBUG | INFO | WARNING | ERROR | CRITICAL

Error handling

from claude_webapi.exceptions import (
    AuthenticationError,
    APIError,
    QuotaExceededError,
    TimeoutError,
    ConversationNotFoundError,
)

try:
    r = await client.generate_content("Hello!")
except AuthenticationError:
    print("Invalid or expired sessionKey.")
except QuotaExceededError as e:
    print(f"Rate limited. Resets in {e.retry_after_s}s.")
except TimeoutError:
    print("Request timed out.")
except ConversationNotFoundError:
    print("Conversation not found.")
except APIError as e:
    print(f"HTTP {e.status_code}: {e}")

References

Metadata

Release files for claude-webapi 1.0.352

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

Source distribution (sdist)

Source distribution for claude-webapi 1.0.352
File Size Uploaded Provenance Actions
claude_webapi-1.0.352.tar.gz 26.2 kB With provenance Details for claude_webapi-1.0.352.tar.gz

Built distribution (wheel)

Table of built distributions (wheels) for claude-webapi 1.0.352
File Interpreter ABI Platform Actions
claude_webapi-1.0.352-py3-none-any.whl Python 3 none any Details for claude_webapi-1.0.352-py3-none-any.whl

Total release size: 51.1 kB

Release files / claude_webapi-1.0.352.tar.gz

Download URL claude_webapi-1.0.352.tar.gz
Size 26.2 kB
Tags Source
SHA-256 checksum
How to use checksums
ea64ac025027dfc1f34f73c376ac8b9f44c67e1f684c4daaf9f5c07efdf80c26
BLAKE2b-256 checksum
How to use checksums
144178f2a7aa353dec75615627f842765bff2c03804863b80cc38d59b3784408
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/6.1.0 CPython/3.13.12

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 May 24, 2026.

Transparency log

Release files / claude_webapi-1.0.352-py3-none-any.whl

Download URL claude_webapi-1.0.352-py3-none-any.whl
Size 24.9 kB
Tags Python 3
SHA-256 checksum
How to use checksums
0e540cdde4458f0458c5cf29c18463f183881be0dee923d743cbd6fcfd6c083b
BLAKE2b-256 checksum
How to use checksums
f87b70606155d8c9f31d4d1e07be3767fbfca47f71a70fdfb1ca8b5e7a8ea805
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/6.1.0 CPython/3.13.12

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 May 24, 2026.

Transparency log

Security for claude-webapi 1.0.352

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.

Full provenance

All 2 files in this release have been uploaded with provenance metadata.

Select from 2 files

Attestation for claude_webapi-1.0.352.tar.gz

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 May 24, 2026.

Transparency log

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

To learn more about protecting yourself from malicious actors, visit our package security documentation.

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