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
- Authenticated scraping. The site requires login; you want each session to carry over cookies + storage without re-authenticating.
- A/B-tested rendering. The site personalises based on cookies; you want each run to see the same variant.
- Device pinning. You want every run to use
one specific Driftstack device profile (the
archetypefield: user agent, screen size, timezone, locale) rather than the account default, so the browser fingerprint stays the same across runs.
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
- Cookies + storage state are stored encrypted at rest.
- Profile metadata + snapshot rows are deleted on account deletion + per the documented retention policy.
- The profile record holds what you set on it (name, description, folder, tags, icon, note, notes, default proxy, geolocation, the exit-IP stop setting) and what the API returns about it (ids, device profile, sizes, timestamps). Put nothing in the free-text fields you do not want stored.
Limits
Profile cap by plan:
| Plan | Profile cap |
|---|---|
| Trial | 1 |
| Starter | 25 |
| Pro | 100 |
| Team | 300 |
| Scale | 1,000 |
| Enterprise | Unlimited |
The earlier plans, no longer offered, keep their caps for the accounts that hold them:
| Earlier plan | Tier id | Profile cap |
|---|---|---|
| Personal | solo_manual | 10 |
| Team | team_manual | 50 |
| Agency | agency_manual | 200 |
| API Starter | api_starter | 25 |
| API Builder | api_builder | 100 |
| API Scale | api_scale | 500 |
Need more? Email support.