Skip to main content
A profile is a named, versioned, encrypted browser state that belongs to your account. A session names a profile when it is created, starts from that state, and can save its changes back as a new version. A session loads only the profile it names. A name or id from another account answers 404, and a session carrying one profile cannot load a second. For a login on one site, saved logins may be enough; a profile also carries page storage and, on request, the Chrome folder. Read routes need the sessions:read scope. All other profile routes need sessions:write. Profile routes answer 501 where profiles are not available.

POST /v1/profiles

Create an empty profile.
The response is 201 with the profile: id, name, domains, persona, country and created_at, plus the optional settings you set. The first save sets persona and country. Errors: 409 profile_conflict when the name exists; 422 invalid_profile for a bad name or setting, or at 200 profiles.

GET /v1/profiles

Returns {"profiles": [...]}. GET /v1/profiles/{name} returns one profile with versions (the count), version (the newest number, 0 when empty) and latest (that version’s index).

DELETE /v1/profiles/{name}

Delete a profile and everything it holds. Returns {"deleted": "shop-login", "objects": 3}, where objects counts the stored objects removed.

Use a profile when creating a session

Send a profile block on POST /v1/session, or profile_id alone to attach read only.
full and folder restart Chrome once inside the session before it is handed over, so the create takes one Chrome launch longer. They work at create only. The session response has a profile block, or null without a profile: name, version, save, restored and coherence. restored holds counts: cookies, localStorage and origins. A folder restore adds folder, folder_version and device, which is kept when the session runs the device the folder was saved under and new when it has its own. Errors on create:

Save modes

replace with domains saves as a merge of those domains, so other domains are not deleted. A save changes only what the session could see: page storage is saved for the origins read back from open tabs and cookie hosts, up to 12, and the storage of any other origin carries forward unchanged.

Read-only sessions

Any number of sessions can use save: "none" on one profile. Each keeps the version it loaded and does not see later saves. A POST /v1/session/{id}/profile/save for that profile answers 409 profile_read_only. To save from the session, change its mode with PATCH /v1/session/{id}/profile.

GET /v1/session/{session_id}/profile

Returns name, version, head_version, behind, mode, save, folder, cache, restored and coherence. Here mode is the save mode as a string and save is a boolean saying whether the session saves. behind is true when another writer has committed since this session loaded. A session with no profile answers 404 no_profile.

PATCH /v1/session/{session_id}/profile

Turn saving on or off, or change the mode, while the session runs. This works with a CDP client connected. The browser and the version it holds do not change.
The answer has the same fields as GET, without head_version and behind.
  • none always works.
  • replace answers 409 profile_conflict when a newer version exists, or when a merge session’s version holds another writer’s changes.
  • merge answers 409 profile_conflict when the version the session loaded has been pruned.
After a refusal the mode is unchanged. Passing these checks does not reserve the profile: a replace session is checked again when it saves.

POST /v1/session/{session_id}/profile/load

Load a profile’s cookies, localStorage and IndexedDB into a running session. The body takes name or profile_id, and optionally save, domains and coherence. The response is {"profile", "version", "save", "restored", "coherence", "persona", "country"}. Errors: 409 session_driven_by_client with a main client connected; 409 profile_full_needs_new_session with full or folder; 409 profile_already_attached when the session carries another profile.

POST /v1/session/{session_id}/profile/save

Save cookies and page storage now. The body is optional: name saves into another profile as a one-off snapshot, and force: true skips the login check. The response is the new version’s index with profile. The Chrome folder is saved only when the session ends, because reading it stops Chrome. Errors: 409 session_driven_by_client with a main client connected; 409 profile_conflict when another writer committed first; 409 profile_probe_failed (failures) when the state fails the login check; 409 profile_read_only; 422 profile_required when no profile is named or loaded.

What is restored

sessionStorage

A new session’s first tab gets the sessionStorage the profile saved, before any page opens, so the page’s first script finds its values. The first tab is context.pages[0] in Playwright, and it is the same tab for raw CDP and the REST routes. Each value goes back only under the origin it was saved from. A tab opened later starts empty, as in any browser. A tab the page opens with window.open copies its opener’s values, and a noopener tab starts empty.
A save reads sessionStorage only from the origin each open tab is on at that moment. If the tab leaves a site before the session closes, that site’s sessionStorage is not saved, and it keeps the values from its last save, if any. To keep it, end the session on that site, or call POST /v1/session/{id}/profile/save while the tab is there. That route answers 409 session_driven_by_client while a CDP client such as Playwright is connected, so disconnect the client, save, and reconnect. The tab stays on its page.
A tab closed before the save, and a frame from another site, are not saved either. A version saved mid-session, or by a session without full or folder, holds no folder. A later full session restores the newest folder and applies the newer cookies and page storage on top. restored.folder_version shows which version the folder came from.

Two sessions on one profile

Both sessions start, because a profile is not locked. What happens next depends on save: Use merge for sessions that write at the same time. While a replace session runs, GET /v1/session/{id}/profile says behind: true once another writer has committed. Switching to merge then keeps its changes. A session that ends with saving on reports the outcome in three places:
  • The close header. DELETE /v1/session/{id} answers 204 with X-Tilion-Profile-Save: saved, conflict, probe_failed, profile_deleted or failed. profile_deleted means the profile was deleted while the session ran: nothing is saved and nothing comes back.
  • The status field. GET /v1/session/{id}/status has profile_save for an hour, including for sessions that ended by idle or expiry: profile, status, held_version, and when they apply version, head_version, error, message and folder. folder holds saved, and when they apply bytes, skipped, replaced_other_writers and cache. folder.replaced_other_writers is true when this save replaced another writer’s folder.
  • Events and webhook. When changes were not saved, the profile gets a save_refused event and a profile.save_refused webhook with session_id, reason, held_version and head_version.

Limits

A version index reports a skipped folder in folder_skipped.

Retention

Set retention_days (1 to 3650) on POST /v1/profiles or PATCH /v1/profiles/{name} to delete older versions after a save and in a periodic sweep. clear_retention: true removes the setting. POST /v1/profiles/{name}/prune with {"keep": 5} deletes by count on request and answers removed_versions, kept and oldest. The newest version is never deleted, and retention never deletes a profile. A replace session holding a version that has been deleted is refused when it saves, with 409 profile_conflict. A merge session saves normally.

Other profile routes

See the login-once guide for a complete example.