OpenHandle Python SDK
The official Python client for the OpenHandle API.
Installation
pip install openhandle
The package supports Python 3.10 and newer and ships full type annotations.
Usage
Create a Test key in the Openhandle dashboard,
store it as OPENHANDLE_TEST_KEY, and create one reusable client:
import os
from openhandle import OpenHandle
openhandle = OpenHandle(api_key=os.environ["OPENHANDLE_TEST_KEY"])
profile = openhandle.instagram.profile("northstar_forge_test")
response = profile.get()
posts = profile.posts.list(freshness="24h")
print(response.data["handle"], len(posts.data))
The key selects the environment. oh_test_ keys return deterministic synthetic
data with a $0.000 actual charge; oh_live_ keys use real public identifiers
and normal billing. Never expose an API key in client-side code.
See the API reference for a typed SDK example for every operation.
Resource selection
The SDK follows one predictable grammar:
openhandle.<platform>.<resource>(reference).<subresource>.<operation>(options)
Only terminal operations such as get, list, search, and fetch perform
network requests. Selecting a resource is synchronous and reusable:
post = openhandle.instagram.post("Db04otPRpRH")
response = post.get()
comments = post.comments.list()
A profile selector accepts a username shorthand or an explicit reference:
openhandle.instagram.profile("openai")
openhandle.instagram.profile("https://www.instagram.com/openai/")
openhandle.instagram.profile(username="12356")
openhandle.instagram.profile(id="25025320")
openhandle.instagram.profile(url="https://www.instagram.com/openai/")
A raw string is never treated as a platform ID. profile("12356") selects the
username 12356; profile(id="12356") selects platform ID 12356. Numeric
reference values are rejected because platform IDs are opaque strings.
Call openhandle.fetch(url) when you do not know which resource a supported
social URL represents. TikTok short links such as tiktok.com/t/… and
vm.tiktok.com/… are rejected by selectors and only work through fetch,
which expands them server-side.
Pagination
A list or search operation returns one typed page:
page = openhandle.instagram.profile("northstar_forge_test").posts.list()
print(page.data, page.has_next_page, page.next_cursor)
next_page = page.next()
items() iterates lazily across pages, one request per page:
for post in openhandle.instagram.profile("northstar_forge_test").posts.items():
print(post["id"])
Async client
AsyncOpenHandle exposes the same resource graph with async terminal
operations:
import asyncio
import os
from openhandle import AsyncOpenHandle
async def main() -> None:
async with AsyncOpenHandle(api_key=os.environ["OPENHANDLE_TEST_KEY"]) as openhandle:
response = await openhandle.instagram.profile("northstar_forge_test").get()
print(response.data["handle"])
async for post in openhandle.instagram.profile("northstar_forge_test").posts.items():
print(post["id"])
asyncio.run(main())
Responses
Every response preserves the public envelope. data stays typed through the
generated models in openhandle.models, and metadata is available on the
response object:
response = openhandle.instagram.profile("northstar_forge_test").get()
response.platform # "instagram"
response.resource # "profile"
response.captured_at # datetime
response.source # "live" or "cache"
response.request_id # stable request identifier for logs and support
response.billing.cost # authoritative charge as a decimal string
A missing metric is None. It is never 0.
Errors and retries
The SDK raises OpenHandleError with the documented fields. Branch on code,
never on message:
from openhandle import OpenHandle, OpenHandleError
try:
response = openhandle.instagram.profile("private_account").get()
except OpenHandleError as error:
print(error.code, error.request_id, error.retryable)
Retryable failures are retried automatically with capped exponential backoff
and Retry-After support. Configure the client, or override per request:
openhandle = OpenHandle(api_key="...", timeout=10.0, max_retries=1)
openhandle.twitter.profile("openai").get(timeout=5.0, max_retries=0)
Locally invalid references raise OpenHandleReferenceError before any request
is made. ReferenceMismatchError reports a social URL that belongs to a
different platform or resource than the selector.
License
Release files for openhandle 1.1.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| openhandle-1.1.0.tar.gz | 48.1 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| openhandle-1.1.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 98.8 kB
Release files / openhandle-1.1.0.tar.gz
| Download URL | openhandle-1.1.0.tar.gz |
|---|---|
| Size | 48.1 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
bdc9a5409dcce6db87f0ee56e6da2c89b6f664cb069a1bacb48748e87b75e3b0
|
|
BLAKE2b-256 checksum How to use checksums |
02b2f515b832be4cba3086942c56297b09e21a36620f21bda29df0fd8fb0f807
|
| 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 Sep 17, 2026.
Transparency logRelease files / openhandle-1.1.0-py3-none-any.whl
| Download URL | openhandle-1.1.0-py3-none-any.whl |
|---|---|
| Size | 50.7 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
323b9e24ed138744a92996a9f40de0b9af75f74d642625657d3f1e54af8e21fe
|
|
BLAKE2b-256 checksum How to use checksums |
7c58b50e7ec474f30b0a3f569ca5fd0669e0cb62209a09c524e4f4c44c1dd370
|
| 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 Sep 17, 2026.
Transparency log