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.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 aprofile 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 usesave: "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
Returnsname, 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.GET, without head_version and behind.
nonealways works.replaceanswers 409profile_conflictwhen a newer version exists, or when amergesession’s version holds another writer’s changes.mergeanswers 409profile_conflictwhen the version the session loaded has been pruned.
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 takesname 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 iscontext.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 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 onsave:
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 withX-Tilion-Profile-Save:saved,conflict,probe_failed,profile_deletedorfailed.profile_deletedmeans the profile was deleted while the session ran: nothing is saved and nothing comes back. - The status field.
GET /v1/session/{id}/statushasprofile_savefor an hour, including for sessions that ended by idle or expiry:profile,status,held_version, and when they applyversion,head_version,error,messageandfolder.folderholdssaved, and when they applybytes,skipped,replaced_other_writersandcache.folder.replaced_other_writersis true when this save replaced another writer’s folder. - Events and webhook. When changes were not saved, the profile gets a
save_refusedevent and aprofile.save_refusedwebhook withsession_id,reason,held_versionandhead_version.
Limits
A version index reports a skipped folder in
folder_skipped.
Retention
Setretention_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.