# 动态代理参数

> 在动态代理的密码中添加参数，即可选择出口国家/地区，并通过粘性会话保持同一 IP。

Canonical URL: https://s1.dev/zh/docs/proxies/parameters

这些参数仅适用于**动态住宅代理**。在仪表盘的**网关入口**卡片中设置**出口国家/地区**和 **IP 模式**后，会自动为你生成这些参数。如果你需要在代码中构造凭据，请参考本页。

> **warn:** 用户名请保持与仪表盘中显示的完全一致，把参数追加到密码末尾。其他形式的凭据都会以 `407 Proxy Authentication Required` 被拒绝。

## 格式

```text
username: USERNAME
password: PASSWORD[_country-CC][_session-NNNNNNNN_ttl-T]
```

| 参数 | 取值 | 作用 |
| --- | --- | --- |
| `_country-CC` | 大写的两位国家/地区代码，例如 `US`、`JP`、`DE` | 通过该国家/地区的 IP 出口。省略时使用全球 IP 池。 |
| `_session-NNNNNNNN` | 恰好 8 位数字 | 使用此 ID 的所有连接都保持同一个出口 IP。 |
| `_ttl-T` | `5`、`10`、`15` 或 `30`（分钟） | 粘性会话的持续时间。使用 `_session` 时必填，未使用时不得添加。 |

请只使用仪表盘**出口国家/地区**菜单中列出的国家/地区。

## 示例

| 目标 | 密码 |
| --- | --- |
| 在全球 IP 池中轮换 | `PASSWORD` |
| 在美国范围内轮换 | `PASSWORD_country-US` |
| 保持同一个日本 IP 10 分钟 | `PASSWORD_country-JP_session-48213907_ttl-10` |
| 保持任意国家/地区的同一个 IP 30 分钟 | `PASSWORD_session-77310452_ttl-30` |

写成代理 URL：

```bash
curl -x "http://USERNAME:PASSWORD_country-US_session-48213907_ttl-10@HOST:PORT" https://ipinfo.io/json
```

## 轮换机制

不使用 `_session` 时，网关会为每个**新的代理连接**选择一个新的出口 IP。HTTPS 请求通过隧道传输，同一隧道中发送的所有请求都使用同一个 IP。因此，复用连接的客户端（keep-alive、`requests.Session`、浏览器连接池）在连接关闭之前会一直使用同一个 IP。

这就是仪表盘中**每次请求轮换 IP** 的含义。如果希望每个请求都使用新 IP，请为每个请求建立新连接，或为每个请求使用不同的会话 ID。

## 粘性会话

在 TTL 内使用同一会话 ID 的连接会从同一个 IP 出口。适用于登录、结账等多步骤流程。

- 要切换 IP，请生成新的会话 ID。
- 住宅 IP 可能在 TTL 结束前下线，此时你的会话会切换到另一个 IP。
- 最长为 30 分钟。如果需要连续数天或数周使用同一个 IP，请改用静态 ISP 代理。

在代码中生成会话 ID：

```python
import random

def rotating_password(base_password, country=None, ttl_minutes=None):
    password = base_password
    if country:
        password += f"_country-{country.upper()}"
    if ttl_minutes:
        assert ttl_minutes in (5, 10, 15, 30)
        session_id = f"{random.randrange(100_000_000):08d}"
        password += f"_session-{session_id}_ttl-{ttl_minutes}"
    return password

print(rotating_password("PASSWORD", country="us", ttl_minutes=10))
# 例如 PASSWORD_country-US_session-04821390_ttl-10
```

```js
function rotatingPassword(basePassword, { country, ttlMinutes } = {}) {
  let password = basePassword;
  if (country) password += `_country-${country.toUpperCase()}`;
  if (ttlMinutes) {
    if (![5, 10, 15, 30].includes(ttlMinutes)) throw new Error('Invalid TTL');
    const sessionId = String(Math.floor(Math.random() * 1e8)).padStart(8, '0');
    password += `_session-${sessionId}_ttl-${ttlMinutes}`;
  }
  return password;
}
```

## 常见错误

| 错误写法 | 正确写法 | 原因 |
| --- | --- | --- |
| 用户名写成 `USERNAME_country-US` | 密码写成 `PASSWORD_country-US` | 参数只从密码中读取。 |
| `_country-us` | `_country-US` | 国家/地区代码必须大写。 |
| `_session-demo`、`_session-abc123` | `_session-12345678` | 会话 ID 必须恰好是 8 位数字。 |
| `_session-12345678_ttl-60` | `_ttl-30` 或更小 | TTL 只能是 5、10、15 或 30。 |
| `PASSWORD_ttl-10` | `PASSWORD_session-12345678_ttl-10` | TTL 需要配合会话使用。 |
| `PASSWORD_session-12345678_ttl-10_country-US` | `PASSWORD_country-US_session-12345678_ttl-10` | 国家/地区参数要放在会话参数之前。 |
| `-cc-US`、`-sessid-`、`zone-` | `_country-US`、`_session-` | 不支持其他服务商的语法。 |

## 静态 ISP 代理

静态 ISP 代理不接受任何参数，请完全按照仪表盘显示的密码使用。添加后缀会导致 `407`。IP 在整个订单期间保持不变。如果某个 IP 有问题，请在仪表盘的**帮助**页面申请更换。