> ## Documentation Index
> Fetch the complete documentation index at: https://docs.surfsky.io/llms.txt
> Use this file to discover all available pages before exploring further.

# Sessions

> Start and stop browsers, reuse persistent profiles, and choose what browser state to save.

A session is a running browser. One-time profiles discard their state when the session stops. Persistent profiles can save cookies and other selected browser data for later sessions.

## One-time profiles

`POST /profiles/one_time` creates and starts a browser. Use it when each task can begin with a fresh profile.

```bash theme={null}
curl --fail-with-body "$SURFSKY_API_BASE_URL/profiles/one_time" \
  -H "X-Cloud-Api-Token: $SURFSKY_API_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{}'
```

Set the environment variables as shown in the [Quickstart](/quickstart#before-you-start). An omitted `proxy` uses an available account pool; if your account has none, supply your own proxy.

The response has `ws_url` and `internal_uuid` at the top level. Connect to `ws_url`, then stop the session with the returned identifier. Cookies, storage, and history from a one-time profile are not saved as a persistent profile.

## Persistent profiles

Create a profile once. `title` and `fingerprint.os` are required:

```bash theme={null}
curl --fail-with-body "$SURFSKY_API_BASE_URL/profiles" \
  -H "X-Cloud-Api-Token: $SURFSKY_API_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "title": "my profile",
    "fingerprint": {"os": "win"},
    "storage_options": {"cookies": true, "localstorage": true}
  }'
```

A successful creation returns HTTP `201` with the profile identifier in `data.uuid`. Save this identifier and use it to start the profile:

```bash theme={null}
curl --fail-with-body -X POST \
  "$SURFSKY_API_BASE_URL/profiles/PROFILE_UUID/start" \
  -H "X-Cloud-Api-Token: $SURFSKY_API_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{}'
```

Creation does not start a browser. Each start restores saved profile state. Settings supplied to `/start` apply to the running session; use `PATCH /profiles/{profile_uuid}` to update stored settings while the profile is stopped.

A persistent profile has one running browser at a time. Starting a profile that is already running returns the running session rather than restarting it, and the settings sent with that request are not applied. Stop the session first when a run needs different start settings. Use a different profile for independent work, and avoid having multiple workers control the same profile.

### What gets saved

`storage_options` selects the data saved with the profile:

| Option           | Default | Data                                   |
| ---------------- | ------- | -------------------------------------- |
| `cookies`        | `true`  | Website cookies                        |
| `passwords`      | `true`  | Browser-saved passwords                |
| `bookmarks`      | `true`  | Bookmarks                              |
| `localstorage`   | `false` | Local storage and related site storage |
| `extensions`     | `false` | Extension state                        |
| `history`        | `false` | Browsing history                       |
| `serviceworkers` | `false` | Service worker data                    |

Enable the storage your application uses. Cookies alone may not preserve a login that also depends on local storage. See [Cookies](/cookies#sessions-that-will-not-stay-logged-in).

### Reuse a login

1. Create a persistent profile with cookies enabled. Enable local storage if the site needs it.
2. Start the profile and open the site's login page.
3. Sign in through your automation or the session's [DevTools](/debugging).
4. Stop the session through the API and wait for the response.
5. Start the same profile and navigate to an authenticated page. Check that the page still recognizes the account before continuing.

The fingerprint and saved storage remain associated with the profile. A website can still expire or revoke its own session. Proxy settings do not guarantee the same exit IP on every run; configure proxy session behavior when IP continuity matters.

### Change the proxy

A saved profile can change its connection in two ways, with different lifetimes.

**Change the stored proxy.** `PATCH` the stopped profile; the next start uses the new value.

```bash theme={null}
curl --fail-with-body -X PATCH \
  "$SURFSKY_API_BASE_URL/profiles/PROFILE_UUID" \
  -H "X-Cloud-Api-Token: $SURFSKY_API_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"proxy": {"tier": "premium", "country": "de"}}'
```

A pool selection is resolved when it is saved, not on each start: the profile stores one concrete proxy from the pool and reuses it every run. The exit IP behind a residential or mobile proxy still changes between sessions; use [session control](/proxies#session-control) when the IP must stay the same. Saving the same selection again pins a different proxy. A stored pool proxy is not re-checked at start, so save the selection again if it stops working.

Send a URL to store your own proxy, or `null` to remove the stored proxy and let later starts select from an available account pool:

```json theme={null}
{ "proxy": "socks5://user:pass@proxy.example.com:1080" }
```

```json theme={null}
{ "proxy": null }
```

Edit a stopped profile. A running profile returns `profile_is_running`; see [errors](/errors#request-errors).

**Override for one session.** Send `proxy` in the start request. It applies to that browser only and leaves the stored proxy unchanged.

```bash theme={null}
curl --fail-with-body -X POST \
  "$SURFSKY_API_BASE_URL/profiles/PROFILE_UUID/start" \
  -H "X-Cloud-Api-Token: $SURFSKY_API_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"proxy": {"tier": "premium", "country": "de"}}'
```

A proxy URL, `open_vpn`, and `wireguard` replace the stored proxy for that run in the same way. A shared-tier override needs a country - `{"proxy": {"tier": "shared", "country": "de"}}` - because a shared request without one leaves the stored proxy in place. An override reaches the browser only on a start that actually launches one; a request that returns an already running session does not apply it.

Read a profile back with [GET /profiles/\{profile\_uuid}](/api-reference/profiles/get-profile) to see its current connection. Account pool proxies are reported as `premium` or `shared` instead of credentials; your own proxies are returned as supplied.

Changing the exit IP does not change the profile's cookies, storage, or fingerprint. A site that tied its session to the previous IP or country can ask for verification again, so keep the country stable unless the account is meant to move. See [proxies](/proxies) for targeting and session options.

## Identifiers

| Identifier                            | Use it for                                                                |
| ------------------------------------- | ------------------------------------------------------------------------- |
| `data.uuid` from profile creation     | Starting, reading, updating, or deleting the saved profile                |
| `internal_uuid` from a start response | Stopping the running browser, scraping, CDP, ChromeDriver, and screencast |

Always use the identifier returned for the operation. Do not depend on profile and session identifiers being different, or on a persistent profile receiving a new identifier on every start.

<span id="session-lifetime" />

<span id="stop-a-session" />

## How a session ends

**Explicit stop.** Send `POST /profiles/{internal_uuid}/stop`. For persistent profiles, a normal stop saves the selected browser state. Wait for completion before starting the next run.

```bash theme={null}
curl --fail-with-body -X POST \
  "$SURFSKY_API_BASE_URL/profiles/INTERNAL_UUID/stop" \
  -H "X-Cloud-Api-Token: $SURFSKY_API_TOKEN"
```

**Inactivity.** The browser stops after `browser_settings.inactive_kill_timeout` seconds without activity. The default is 30 seconds; the accepted range is 1–3600 seconds. CDP commands, ChromeDriver requests, and scraping activity update the activity timer. An open but idle connection is not sufficient.

```json theme={null}
{ "browser_settings": { "inactive_kill_timeout": 300 } }
```

Set a longer timeout for work that includes pauses, such as manual input. A longer timeout also leaves an abandoned browser running longer.

**Failure.** A browser or infrastructure failure can end the session before a normal stop completes. Recent unsaved state may be lost. Check active sessions before reconnecting or starting replacement work.

<span id="find-running-sessions" />

## Finding what is running

```bash theme={null}
curl --fail-with-body "$SURFSKY_API_BASE_URL/profiles/active" \
  -H "X-Cloud-Api-Token: $SURFSKY_API_TOKEN"
```

`data` contains an array of sessions with `internal_uuid`, `profile_uuid`, `one_time`, `started_at`, and `active_seconds`. Use `one_time` to identify disposable sessions; do not infer profile type from whether an identifier is present.

This lists running browsers only. [GET /profiles](/api-reference/profiles/list-profiles) lists saved profiles page by page, each with a `status` of `started` or `stopped`.

Stop sessions owned by completed or failed jobs. Age alone does not prove that a session is abandoned.

<Warning>
  `POST /profiles/stop` stops every running browser on the account, including
  browsers used by other workers. Its response reports `stopped` and `failed`
  separately.
</Warning>

## Browser capacity

A running browser uses one [concurrency slot](/concurrency) until it stops. A failed or interrupted start request can have an uncertain outcome, so check for an existing session before retrying it.
