Skip to content

SDKs

Thin, typed clients for JavaScript/TypeScript and Python — built-in retries, typed errors, one-line page fetches.

Install

The SDKs live in the repository under packages/ and are not published yet.

JavaScript / TypeScript
cd packages/sdk-js && npm install && npm run build
npm install ./packages/sdk-js        # in your project
Python
pip install ./packages/sdk-python    # requires httpx

JavaScript / TypeScript

JS SDK
import { Teneo } from "@teneo/contents";

const client = new Teneo({ apiKey: process.env.LIVE_WEB_DATA_API_KEY, baseUrl: "https://livewebdata.com/api" });

const page = await client.getPage("https://example.com/article", { country: "de", format: "markdown" });
console.log(page.title, page.credits);

const res = await client.contents({ urls: ["https://example.com/a", "https://example.com/b"] });
const account = await client.account();

Python

Python SDK
import os
from teneo import Teneo

client = Teneo(api_key=os.environ["LIVE_WEB_DATA_API_KEY"], base_url="https://livewebdata.com/api")

page = client.get_page("https://example.com/article", country="de", format="markdown")
print(page.title, page.credits)

res = client.contents(urls=["https://example.com/a", "https://example.com/b"])
account = client.account()

Both clients read the key from LIVE_WEB_DATA_API_KEY and the base URL from LIVE_WEB_DATA_API_BASE_URL when you don't pass them.

Methods

JSPythonDescription
contents(request, { idempotencyKey })contents(urls=…, country_code=…, text=…, html=…, livecrawl_timeout=…, render=…, render_fallback=…, idempotency_key=…)Raw POST /v1/contents (1–10 URLs). render_fallback=False / renderFallback: false turns the default browser fallback off
getPage(url, opts)get_page(url, country=…, format=…)One URL → { title, url, content, credits, source }; raises if that URL failed. format: "html" requests the HTML (html: true)
account()account()GET /v1/account

Errors

ErrorWhen
TeneoAuthError401 / 403 — key invalid, revoked or suspended
TeneoInsufficientCreditsError402
TeneoRateLimitError429 after all retries (retryAfter / retry_after)
TeneoIdempotencyError409 — the idempotency key was used with a different request, or its result expired (15 minutes)
TeneoRestrictedTargetError451
TeneoConnectionErrorNetwork error or timeout after all retries, or a 2xx answer cut while it was read. The API may have received the request: repeat it with the error's idempotencyKey / idempotency_key
TeneoPendingErrorStill 202 when maxWaitMs / max_wait ran out; idempotencyKey / idempotency_key collects the result later
TeneoPageErrorgetPage / get_page: the URL failed (tag, e.g. CRAWL_NOT_FOUND)
TeneoAPIErrorBase class (status, tag, requestId, and idempotencyKey / idempotency_key: the key of a contents() call, else null / None)

Retries

Both SDKs retry 429 (respecting Retry-After), 5xx, network errors, a 2xx answer cut while it is read and — for getPage — CRAWL_LIVECRAWL_TIMEOUT, up to 3 times with exponential backoff and jitter. 400, 401, 402, 403, 409 and 451 are never retried. Configure with maxRetries / max_retries.

Every attempt of one contents() call sends the same Idempotency-Key, so a retry picks up the first fetch and is never charged twice (render requests included). A fetch that runs longer than about 100 seconds answers 202; the SDKs repeat it after Retry-After until the result arrives, for up to 5 minutes (maxWaitMs / max_wait). These repeats do not count as retries. See Long requests.

Without your own key, the SDKs create one per contents() call. When the retries run out, the error carries that key: call contents() again with the same request and { idempotencyKey: e.idempotencyKey } / idempotency_key=e.idempotency_key within 15 minutes, and a fetch the API already received returns its result instead of being charged again. Better: always pass your own key (one per logical request, for example per row of your input), so a request cut by a network error, a timeout or a deploy can be retried without a second charge even after your process restarts.