Quickstart
This guide takes you from a fresh signup to your first iPhone Safari session from code. Allow about five minutes. A session is a phone browser running in Driftstack’s cloud — your code tells it where to go and what to do, and it reports back what it sees.
This code quickstart requires a paid tier with API access. Every paid Driftstack tier, including the Manual tiers, can create a
ds_live_…customer API key. On Free, start in the desktop app instead: browser sign-in automatically stores a restrictedds_test_…device credential, so there is no customer API key to create or paste. That device credential is for the supported desktop surface; it is not a general sandbox or SDK key.
You will need:
- A Driftstack account (sign up or sign in)
- Any paid Driftstack tier (Manual, API, or Enterprise)
- A
ds_live_…customer API key (created in the dashboard under API keys) - Node.js 18+, Python 3.10+, or Go 1.22+
1. Get an API key
After signing up and verifying your email:
- Open app.driftstack.dev/api-keys.
- Click Create key, give it a name (e.g.
quickstart), and copy the value. The key is shown once. - Export it in your shell:
export DRIFTSTACK_API_KEY="ds_live_…"
Customer API keys are scoped to the account that created them and carry the
ds_live_ prefix on every paid tier, including Manual. Free does not mint
customer API keys: its ds_test_… value is the restricted device credential
the desktop app obtains and stores automatically after browser authorization.
If an account is downgraded to Free, existing ordinary API keys and OAuth
access tokens receive 403 Forbidden. They become usable again after an
upgrade unless they were revoked or expired. A denied response uses the normal
RFC 9457 Forbidden problem and an actionable detail such as
The "apiAccess" feature is not available on the "free" tier. Upgrade to a tier that includes this feature.
2. Install the SDK
Pick the language you want to use. See SDK installation for full details.
TypeScript / Node.js:
npm install @driftstack/sdk
Python:
pip install driftstack-sdk
Go:
go get github.com/driftstackdev/driftstack-api/packages/sdk-go
All three SDKs are published pre-1.0: TypeScript on npm, Python on PyPI, and Go as a tagged module. Keep your package-manager lockfile, Python constraints, or
go.sumunder version control for reproducible installs.
3. Run your first session
This snippet creates a session, navigates to a URL, captures a screenshot, and tears the session down.
TypeScript:
import { Driftstack } from '@driftstack/sdk';
const client = new Driftstack({ apiKey: process.env.DRIFTSTACK_API_KEY! });
const session = await client.sessions.create({ label: 'quickstart' });
await client.sessions.navigate(session.id, { url: 'https://example.com' });
const shot = await client.sessions.capture(session.id, { kind: 'screenshot' });
console.log('captured:', shot);
await client.sessions.destroy(session.id);
Python (sync):
import os
from driftstack import Driftstack
with Driftstack(api_key=os.environ["DRIFTSTACK_API_KEY"]) as client:
session = client.sessions.create({"label": "quickstart"})
client.sessions.navigate(str(session.id), {"url": "https://example.com"})
shot = client.sessions.capture(str(session.id), {"kind": "screenshot"})
print("captured:", shot)
client.sessions.destroy(str(session.id))
Go:
package main
import (
"context"
"log"
"os"
driftstack "github.com/driftstackdev/driftstack-api/packages/sdk-go"
)
func main() {
client := driftstack.New(os.Getenv("DRIFTSTACK_API_KEY"))
defer client.Close()
ctx := context.Background()
session, err := client.Sessions.Create(ctx, &driftstack.CreateSessionRequest{Label: "quickstart"})
if err != nil { log.Fatal(err) }
if _, err := client.Sessions.Navigate(ctx, session.ID, &driftstack.NavigateRequest{URL: "https://example.com"}); err != nil {
log.Fatal(err)
}
if _, err := client.Sessions.Capture(ctx, session.ID, &driftstack.CaptureRequest{Kind: "screenshot"}); err != nil {
log.Fatal(err)
}
if err := client.Sessions.Destroy(ctx, session.ID); err != nil {
log.Fatal(err)
}
}
4. What happened
client.sessions.create()reserved one of your account’s concurrent session slots. Each tier has a concurrent cap (Free: 1, API Starter: 2, API Builder: 8, API Scale: 24 — see pricing). Exceeding the cap returns 429.client.sessions.navigate()drove the iPhone Safari runtime to the URL on Driftstack’s WebKit build. The runtime is built from Apple’s WebKit source directly — not a Chromium-stealth shim pretending to be Safari.client.sessions.capture()returned a{ kind, data, encoding, byte_size, duration_ms }object. For a screenshot,datais the PNG base64-encoded (encoding: "base64"), so decode it to bytes before saving — e.g.fs.writeFileSync('shot.png', Buffer.from(shot.data, 'base64')). Adom_snapshotcapture instead returns the raw HTML as UTF-8 text (encoding: "utf8").client.sessions.destroy()released the concurrent slot. Only free-tier sessions stop on their own (at the 20-minute cap) — on paid tiers a forgotten session holds its slot until you destroy it.
5. Next steps
- Profile management — persistent profiles let a session resume cookies, storage, and trust signals across runs.
- Session lifecycle — full lifecycle reference (states, the free-tier 20-minute duration cap, recovery on reconnect).
- Agent sessions — natural-language decompose-and-execute on top of any driver session. Three operational modes: AI (default), manual (pass-through), pair (interactive takeover state machine). Live transcript stream via Server-Sent Events.
- Bundled LLM and BYOK Anthropic — the two LLM rails agent sessions can use. BYOK encrypts your Anthropic key at rest + decrypts in-memory only at execution; the bundled rail uses a deployment-managed budget for accounts that don’t want to manage their own key.
- Idempotency keys —
Idempotency-Keyis honoured on four endpoints: agent-session creation, agent-session messages, and the two billing checkouts. It is not honoured onPOST /v1/sessions— thesessions.create()call above. Retrying that after a timeout mints a second session and takes another concurrent slot, so guard it yourself (reuse the session id you already got back, or checkclient.sessions.list()before retrying). - Webhook event catalog — push notifications when sessions transition state, billing events fire, etc.
- API versioning policy — what changes are additive, what triggers
/v2/*, deprecation cycles.
Stuck? Email support@driftstack.dev. Include your account ID (acc_…) + the request ID from any error response (returned in the x-request-id header) so we can trace it.