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

# Custom Proxy

> Requirements for running your own secret proxy with Notte sessions

> [!TIP]
>
> Read [the Notte skill](https://notte.cc/skill.md) and follow its setup instructions when setting up Notte or building browser automation. This is the shared source for CLI setup, authentication, and the browser-to-code workflow.

You can use a proxy you run yourself as a Notte [secret proxy](https://docs.notte.cc/features/sessions/secret-proxies/overview.md), for example one connected to your own vault. Notte sends it the browser's traffic to the hosts you list, and nothing else.

## Requirements

Your proxy must:

1. **Be reachable on a public address**, as `http://host:port` or `https://host:port`. With `https://`, its TLS certificate must be valid for that hostname, issued by a public CA or by the CA you send in `ca_certificate`.
2. **Speak HTTP proxy protocol**: `CONNECT host:443` tunnels for HTTPS sites, and absolute-form requests (`GET http://host/path`) for plain HTTP sites.
3. **Accept Basic auth** in the `Proxy-Authorization` header if you set `username` and `password`, and answer `407` to wrong credentials. Notte then fails the browser's request with `502`.
4. **Decrypt HTTPS for the listed hosts only**, presenting a certificate for the requested host issued by your CA. Send that CA certificate, never its private key, in `ca_certificate`. The browser trusts it for the listed hosts in that session only.
5. **Replace stand-ins with real values only on requests to the listed hosts.** If a value cannot be swapped, return an error instead of forwarding the stand-in.
6. **Replace real values with stand-ins in responses** from the listed hosts, so a site that sends a real value back does not expose it to the browser, the agent, screenshots, recordings or network logs. See [why this matters](https://docs.notte.cc/features/sessions/secret-proxies/overview.md#mask-real-values-in-responses).
7. **Forward requests unchanged apart from the swapped values**, over a new TLS connection to the site that verifies the site's certificate.

## Share the exit IP

To make the site see one IP address for the whole session, send your proxy's outgoing connections for the listed hosts through Notte's proxy gateway with a [gateway credential](https://docs.notte.cc/features/sessions/secret-proxies/overview.md#share-the-exit-ip). Use `proxy_url_tls` if your proxy can use TLS to its upstream, or `proxy_url_plain` if it cannot, and start the session with the same `sticky_session`, and the same `country` or `city`, on its `notte` entry.

```bash cURL theme={null}
# Your proxy's upstream for listed hosts: Notte's gateway with a minted credential
UPSTREAM=$(curl -s -X POST https://api.notte.cc/proxies/gateway/credentials \
  -H "Authorization: Bearer $NOTTE_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"country": "us", "sticky_session": "checkout-4821"}' | jq -r '.proxy_url_tls')

# Check it: this request leaves from the same exit as a session with the same sticky_session
curl -s --proxy "$UPSTREAM" https://api.ipify.org
```

The credential is valid for your plan's maximum session duration, so mint a new one for each session or before it expires.

## Test your proxy

Check that a listed host goes through your proxy and presents a certificate from your CA:

```bash cURL theme={null}
# Through your proxy, a listed host must present a certificate issued by your CA.
# --proxy-cacert verifies the proxy's own certificate with your CA; drop it if the
# proxy uses a certificate from a public CA.
curl -sv -o /dev/null \
  --proxy https://secret-proxy.example.com:443 \
  --proxy-user "YOUR_PROXY_USERNAME:YOUR_PROXY_PASSWORD" \
  --proxy-cacert your-ca.pem \
  --cacert your-ca.pem \
  https://api.stripe.com/
```

You can also save the proxy in the console with the Custom preset and run **Test connection**, which checks the address, the connection, the credentials and the CA. See [Save the configuration in the console](https://docs.notte.cc/features/sessions/secret-proxies/overview.md#save-the-configuration-in-the-console).

## Start a session

```python start_session.py theme={null}
from pathlib import Path

from notte_sdk import NotteClient
from notte_sdk.types import NotteProxy, ProxySettings, SecretProxy

client = NotteClient()

proxies: list[ProxySettings] = [
    # The session's exit for every host you do not list
    NotteProxy.from_country("us"),
    # Your secret proxy, for the listed hosts only
    SecretProxy(
        server="https://secret-proxy.example.com:443",
        username="YOUR_PROXY_USERNAME",
        password="YOUR_PROXY_PASSWORD",
        ca_certificate=Path("your-ca.pem").read_text(),
        hosts=["api.stripe.com", "*.adyen.com"],
    ),
]

with client.Session(proxies=proxies) as session:
    # Server, hosts and CA fingerprints; never the credentials or the certificate
    assert session.response is not None
    summary = session.response.secret_proxy
    if summary is not None:
        print(summary.server, summary.hosts, summary.ca_sha256)
```

```typescript start_session.ts theme={null}
import { readFileSync } from 'node:fs';
import { NotteClient, type NotteProxy, type SecretProxy } from 'notte-sdk';

const client = new NotteClient();

// The session's exit for every host you do not list
const exit: NotteProxy = { type: 'notte', country: 'us' };

// Your secret proxy, for the listed hosts only
const secret: SecretProxy = {
  type: 'secret',
  server: 'https://secret-proxy.example.com:443',
  username: 'YOUR_PROXY_USERNAME',
  password: 'YOUR_PROXY_PASSWORD',
  ca_certificate: readFileSync('your-ca.pem', 'utf8'),
  hosts: ['api.stripe.com', '*.adyen.com'],
};

await client.Session({ proxies: [exit, secret] }).use(async (session) => {
  // Server, hosts and CA fingerprints; never the credentials or the certificate
  const summary = session.getResponse()?.secret_proxy;
  if (summary) {
    console.log(summary.server, summary.hosts, summary.ca_sha256);
  }
});
```


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.