> ## 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.

# Selenium

> Connect Selenium to a Surfsky browser through ChromeDriver, open a page, and stop the session.

Selenium talks to a Surfsky browser over HTTP through a ChromeDriver that runs next to it. Start the browser with `enable_chromedriver: true` (the default is `false`). No local ChromeDriver or Chrome is needed.

<Warning>
  ChromeDriver can leave script artifacts that detection scripts identify. For sites with bot protection, use a patched fork of [Playwright](/quickstart/playwright) or [Puppeteer](/quickstart/puppeteer), or use a Surfsky [SDK](/sdk).
</Warning>

<span id="installation" />

## Prerequisites

Set your [API token and base URL](/quickstart#before-you-start), then install the packages:

```bash theme={null}
pip install selenium requests
```

Other than `enable_chromedriver`, the example uses default start options, including your account's default proxy pool. Proxy, fingerprint, and other options are in the [API reference](/api-reference/profiles/start-one-time-session).

<span id="basic-example" />

## Run an example

The example starts a one-time browser, connects, opens a page, prints its title, and stops the session. To keep cookies and login state between runs, start a [persistent profile](/sessions#persistent-profiles) instead; the connection code is the same.

Save as `surfsky_selenium.py`:

```python theme={null}
import os
import requests
from selenium import webdriver

base_url = os.environ["SURFSKY_API_BASE_URL"].rstrip("/")
headers = {"X-Cloud-Api-Token": os.environ["SURFSKY_API_TOKEN"]}

response = requests.post(
    f"{base_url}/profiles/one_time",
    json={"enable_chromedriver": True},
    headers=headers,
    timeout=120,
)
response.raise_for_status()
session = response.json()

driver = webdriver.Remote(
    command_executor=f"{base_url}/chromedriver/{session['internal_uuid']}",
    options=webdriver.ChromeOptions(),
)
driver.get("https://example.com")
print(driver.title)
driver.quit()

requests.post(f"{base_url}/profiles/{session['internal_uuid']}/stop", headers=headers, timeout=120)
```

```bash theme={null}
python surfsky_selenium.py
```

Expected output:

```text theme={null}
Example Domain
```

<span id="key-points" />

## Connection settings

Use `/chromedriver/{internal_uuid}` as `command_executor`, not the CDP `ws_url`. The URL grants access to the browser, so keep it private. Do not pass local launch arguments for proxy or fingerprint; those are set in the start request. `chromedriver_not_enabled` means the browser was started without the flag.

## Stop the session

`driver.quit()` ends the WebDriver session but leaves the browser running, because ChromeDriver attached to a browser it did not launch. Stop the session through the API with the `internal_uuid` from the start response, as the example does:

```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"
```

Otherwise the browser stops after the inactivity timeout, 30 seconds by default.
