Skip to main content

Profiles

A profile is a reusable, named browser identity (device profile + saved browser state). The /v1/profiles responses show the profile's metadata; cookies, localStorage, and IndexedDB are stored separately and managed by Driftstack. Save a copy of a profile's settings with POST /v1/profiles/:id/snapshots and restore it into a new profile later via POST /v1/profile-snapshots/:id/restore.

When to use a profile

If your automation doesn't care about identity continuity, skip profiles: a session started without one runs as a random current iPhone your plan includes (pass archetype to pin one).

POST /v1/profiles — mint

POST /v1/profiles
Authorization: Bearer ds_live_…
Content-Type: application/json

{
  "name": "us-east-sales-bot",
  "archetype": "iphone15_ios18_7_safari26_5",   ← optional; omitted, a random iPhone model open for new profiles on your plan
  "description": "Sales-team account for east-coast scraping.",
  "folder": "Sales",                            ← optional, ≤32 chars
  "tags": ["us-east", "scraping"],              ← optional, ≤12 unique, ≤24 chars each
  "icon": "🛒",                                  ← optional, short emoji (synced per-account)
  "note": "warmed up",                          ← optional, ≤280 chars
  "default_proxy_id": "6f1c2a9e-…",             ← optional, a saved proxy's id (a bare UUID)
  "geolocation": { "latitude": 40.7128, "longitude": -74.006 },   ← optional
  "stop_on_exit_ip_change": false               ← optional
}

→ 200 OK
{
  "id": "prof_…",
  "name": "us-east-sales-bot",
  "archetype": "iphone15_ios18_7_safari26_5",
  "description": "Sales-team account for east-coast scraping.",
  "folder": "Sales",
  "tags": ["us-east", "scraping"],
  "icon": "🛒",
  "note": "warmed up — ready for checkout flows",
  "notes": "Signed in as the sales test account. Cart has two items.",
  "default_proxy_id": "6f1c2a9e-…",
  "proxy_choice": "bound",
  "geolocation": { "latitude": 40.7128, "longitude": -74.006, "accuracy": 50 },
  "stop_on_exit_ip_change": false,
  "revision": 3,
  "last_used_at": "2026-05-11T12:00:00.000Z",
  "size_bytes": 12900000,
  "last_saved_at": "2026-05-11T12:00:00.000Z",
  "created_at": "2026-05-01T00:00:00.000Z",
  "updated_at": "2026-05-11T12:00:00.000Z",
  "deleted_at": null,
  "purges_at": null
}

The response is a flat profile object — no envelope. Profile ids are prefixed prof_. The archetype field is a lowercase id (1–120 chars) identifying a Driftstack-managed device profile; if you omit it, the profile gets a randomly chosen iPhone model from those your plan includes that are open for new profiles (GET /v1/archetypes lists the models; new_profiles says which are open). Browser state (cookies, localStorage, etc.) is created on first use and is not part of the create request.

size_bytes is the byte size of the profile's saved browser-state store, and last_saved_at is when it was last written back — both null until the profile is first used and saved. Use them to surface per-profile and account-wide storage usage.

notes is free text kept with the profile — the same notes the desktop app's session window shows under Notes. Plain text, UTF-8, at most 16 KiB; null until something is written. Set or clear it with PATCH /v1/profiles/:id ({ "notes": null } clears).

GET /v1/profiles — list

GET /v1/profiles?limit=25
Authorization: Bearer ds_live_…

→ 200 OK
{
  "data": [ /* Profile objects */ ],
  "has_more": true,
  "next_cursor": "eyJ0aWQiOi…"   ← null when no more pages
}

Cursor pagination. Default page size 50; max 100. Pass the previous response's next_cursor as ?cursor= on the next request.

GET /v1/profiles/:id

GET /v1/profiles/prof_…
Authorization: Bearer ds_live_…

→ 200 OK
{
  "id": "prof_…",
  "name": "us-east-sales-bot",
  "archetype": "iphone15_ios18_7_safari26_5",
  "description": "Sales-team account for east-coast scraping.",
  "folder": "Sales",
  "tags": ["us-east", "scraping"],
  "icon": "🛒",
  "note": "warmed up — ready for checkout flows",
  "notes": "Signed in as the sales test account. Cart has two items.",
  "default_proxy_id": "6f1c2a9e-…",
  "proxy_choice": "bound",
  "geolocation": { "latitude": 40.7128, "longitude": -74.006, "accuracy": 50 },
  "stop_on_exit_ip_change": false,
  "revision": 3,
  "last_used_at": "2026-05-11T12:00:00.000Z",
  "size_bytes": 12900000,
  "last_saved_at": "2026-05-11T12:00:00.000Z",
  "created_at": "2026-05-01T00:00:00.000Z",
  "updated_at": "2026-05-11T12:00:00.000Z",
  "deleted_at": null,
  "purges_at": null
}

PATCH /v1/profiles/:id — update

PATCH /v1/profiles/prof_…
Authorization: Bearer ds_live_…
Content-Type: application/json

{
  "name": "us-east-sales-bot-v2",
  "description": "Renamed after the 2026-05 reorg.",
  "folder": null,
  "tags": ["us-east", "scraping", "v2"]
}

→ 200 OK
{
  "id": "prof_…",
  "name": "us-east-sales-bot",
  "archetype": "iphone15_ios18_7_safari26_5",
  "description": "Sales-team account for east-coast scraping.",
  "folder": "Sales",
  "tags": ["us-east", "scraping"],
  "icon": "🛒",
  "note": "warmed up — ready for checkout flows",
  "notes": "Signed in as the sales test account. Cart has two items.",
  "default_proxy_id": "6f1c2a9e-…",
  "proxy_choice": "bound",
  "geolocation": { "latitude": 40.7128, "longitude": -74.006, "accuracy": 50 },
  "stop_on_exit_ip_change": false,
  "revision": 3,
  "last_used_at": "2026-05-11T12:00:00.000Z",
  "size_bytes": 12900000,
  "last_saved_at": "2026-05-11T12:00:00.000Z",
  "created_at": "2026-05-01T00:00:00.000Z",
  "updated_at": "2026-05-11T12:00:00.000Z",
  "deleted_at": null,
  "purges_at": null
}

name, description, folder, tags, icon, note, notes, default_proxy_id, geolocation and stop_on_exit_ip_change are patchable (plus proxy_choice and expected_revision, described in the API reference) — folder: null files the profile back under no folder, and tags is an exact-set replace ([] clears them). To change the device profile (the archetype field), clone the profile via POST /v1/profiles/:id/clone and discard the old one (the device profile is set at create time and stays fixed for the life of the profile).

DELETE /v1/profiles/:id

DELETE /v1/profiles/prof_…
Authorization: Bearer ds_live_…

→ 204 No Content

The profile moves to the recycle bin (Trash): hidden from the list, restorable for at least 7 days with POST /v1/profiles/:id/restore, then removed for good with its persisted browser state. GET /v1/profiles/trash lists the bin; ?permanent=true on the DELETE, or DELETE /v1/profiles/:id/purge on a profile already in the bin, removes it at once. Sessions already running with this profile keep running but can't be pinned to it again. Idempotent: a second DELETE on the same id returns 204. A restore needs a free profile slot on your plan and a restore left for the rolling 30 days; otherwise it answers 429 tier-limit (restore_needs_slot or restore_cap) and the profile stays in the bin. While an agent session runs on the profile, ?permanent=true and /purge are refused with 409: stop the session first.

Snapshots

Profile snapshots are frozen copies of a profile's settings (name, device profile, description). Restoring one creates a new profile with those settings. Snapshots do not save browser data such as cookies or logins, so the restored profile starts signed out:

# Capture
POST /v1/profiles/prof_…/snapshots
Authorization: Bearer ds_live_…
Content-Type: application/json

{ "label": "before-2026-05-12-relogin", "description": "Last-known-good." }

→ 201 Created
{
  "id": "psnap_…",
  "parent_profile_id": "prof_…",
  "label": "before-2026-05-12-relogin",
  "description": "Last-known-good.",
  "parent_archetype": "iphone15_ios18_7_safari26_5",
  "parent_name": "us-east-sales-bot",
  "captured_at": "2026-05-12T12:00:00.000Z",
  "created_at": "2026-05-12T12:00:00.000Z"
}

# List per profile (cursor-paginated; same shape as /v1/profiles)
GET /v1/profiles/prof_…/snapshots

# Restore into a NEW profile (the source snapshot is immutable)
POST /v1/profile-snapshots/psnap_…/restore
Authorization: Bearer ds_live_…
Content-Type: application/json

{ "name": "us-east-sales-bot-restored" }

→ 200 OK   ← returns the newly minted profile object

Snapshot ids are prefixed psnap_. The restore endpoint lives under /v1/profile-snapshots, not under /v1/profiles/<parent>/snapshots. Each restore creates a fresh profile; the snapshot itself is immutable.

Privacy + retention

Limits

Profile cap by plan:

PlanProfile cap
Trial1
Starter25
Pro100
Team300
Scale1,000
EnterpriseUnlimited

The earlier plans, no longer offered, keep their caps for the accounts that hold them:

Earlier planTier idProfile cap
Personalsolo_manual10
Teamteam_manual50
Agencyagency_manual200
API Starterapi_starter25
API Builderapi_builder100
API Scaleapi_scale500

Need more? Email support.

Support

[email protected].