Guides / Build with / Python SDK

Python SDK

Typed sync and async Python client backed by httpx: domain resources, client/geo matrix defaults, automatic cursor pagination, one-call multipart publishing and credit telemetry.

Installation

Requires Python 3.10+. Install from PyPI or directly from the repository subdirectory:

PyPIGit
pip install tikultra

Sync and async clients

Import TikUltra for synchronous pipelines or AsyncTikUltra for asyncio workloads. Both read TIKULTRA_KEY from the environment if api_key is omitted and pool persistent HTTP/2-ready connections when used as context managers.

Sync (TikUltra)Async (AsyncTikUltra)client_example.py
1from tikultra import TikUltra
2
3with TikUltra(api_key="tu_live_...") as client:
4    video = client.video.get("7705852133855161377")
5    profile = client.user.profile("acme")
6    pdp = client.shop.pdp("1729481038291048421")
7    print(video["aweme_id"], profile["user"]["unique_id"], pdp.credits_cost)

Every resource namespace maps 1:1 to the gateway surface: client.video, client.user, client.feed, client.search, client.tako, client.creator, client.douyin, client.shop, client.live, client.series, client.music, client.hashtag, client.account, client.devices, client.crypto and client.jobs, plus client.resolve(...), client.id_converter(...), client.translate(...) and raw client.request(method, path, ...).

Client & geo matrix defaults

Pin default os, app_flavour, app_version, region, city or device_id once on the client constructor, and override any field per call via keyword arguments:

Python SDKmatrix.py
1from tikultra import TikUltra
2
3with TikUltra(
4    api_key="tu_live_...",
5    os="android",
6    app_flavour="tiktok",
7    app_version="47.5.41",
8    region="US",
9    city="los_angeles",
10) as client:
11    # Uses Los Angeles Android 47.5.41 defaults
12    us_fyp = client.feed.persona_fyp("specialty coffee")
13
14    # Per-call override: run on iOS TikTok 47.5.0 out of Tokyo
15    jp_search = client.search.query(
16        "matcha latte",
17        os="ios",
18        app_version="47.5.0",
19        region="JP",
20        city="tokyo",
21    )

Automatic cursor pagination

client.paginate(...) walks any paginated GET or POST endpoint using the unified { cursor, has_more } contract and stops automatically when has_more is false or max_pages is reached:

Sync iteratorAsync iteratorpaginate.py
1from tikultra import TikUltra
2
3with TikUltra(api_key="tu_live_...") as client:
4    for page in client.paginate("GET", "/v1/video/comments", params={"aweme_id": "7705852133855161377", "count": 50}, max_pages=10):
5        for comment in page["comments"]:
6            print(comment["cid"], comment["text"])

Multipart video & slideshow publishing

Pass file paths, raw bytes, or binary streams directly to client.account.upload_video and client.account.upload_slideshow:

Python SDKpublish.py
1from tikultra import TikUltra
2
3with TikUltra(api_key="tu_live_...") as client:
4    post = client.account.upload_video(
5        account_id="acc_creator_01",
6        file="launch.mp4",
7        caption="Launching v2 today #devtools #engineering",
8        visibility="public",
9    )
10    carousel = client.account.upload_slideshow(
11        account_id="acc_creator_01",
12        files=["slide_1.jpg", "slide_2.jpg"],
13        title="Architecture notes",
14        caption="Swipe through the latency breakdown",
15    )
16    print(post["aweme_id"], carousel["aweme_id"])

Response credit & trace metadata

Every SDK call returns an APIResponse wrapper that behaves like the decoded dictionary (res["aweme_id"], "items" in res) while exposing typed gateway headers:

AttributeTypeDescription
res.datadict[str, Any]Decoded JSON response payload
res.credits_costintCredits charged for this call (x-credits-cost, 0 on errors)
res.credits_tierstr | NoneBilling tier (primitive, standard, heavy, premium)
res.credits_remainingint | NoneRemaining key balance (x-credits-remaining)
res.request_idstr | NoneGateway trace ID (x-request-id)
res.cursor / res.has_morestr | None / boolNormalized pagination state on list responses

Typed exception handling

Transient 429 and 5xx responses are retried automatically up to max_retries (default 2), honoring Retry-After. Non-retryable or exhausted failures raise typed subclasses of TikUltraError:

Python SDKerrors.py
1from tikultra import (
2    TikUltra,
3    AuthenticationError,
4    InsufficientCreditsError,
5    PermissionDeniedError,
6    RateLimitError,
7    UpstreamError,
8)
9
10with TikUltra(api_key="tu_live_...", max_retries=3) as client:
11    try:
12        res = client.video.get("7705852133855161377")
13    except RateLimitError as err:
14        print("Rate limited, retry after:", err.retry_after, err.request_id)
15    except InsufficientCreditsError as err:
16        print("Top up key balance:", err.code, err.credits_cost)
17    except (AuthenticationError, PermissionDeniedError) as err:
18        print("Auth or plan gate:", err.status_code, err.code)
19    except UpstreamError as err:
20        print("Upstream mobile error (0 credits charged):", err.request_id)