Skip to content

Repository files navigation

Gemini Web to API logo

把 Gemini 网页端封装成 OpenAI / Claude / Gemini 兼容接口的本地代理服务。

基于网页端逆向实现,依赖 Google Gemini Web 的私有请求结构。适合个人研究和本地客户端接入。

能力概览

能力 OpenAI Claude Gemini 原生
文本对话
流式输出 实时流 实时流 实时流
Thinking Level
多轮上下文 实验性
图片/文件输入
工具调用 实验性桥接 桥接 桥接

快速开始

cp .env.example .env
# 编辑 .env,至少填写 COOKIE_SYNC_TOKEN
go run cmd/server/main.go

服务默认监听 http://localhost:8787,API 文档 http://localhost:8787/docs

存活检查:GET /health;Gemini 账号就绪检查:GET /ready(无健康账号时返回 503)。

基础配置

获取cookie

  1. 请访问gemini.google.com并登录
  2. F12ApplicationStorageCookies
  3. 复制__Secure-1PSID__Secure-1PSIDTS的值
PORT=8787
COOKIE_SYNC_TOKEN=你的管理密钥
PROXY_URL=http://127.0.0.1:10808

单账号模式直接填写 Cookie:

GEMINI_1PSID=你的 __Secure-1PSID
GEMINI_1PSIDTS=可选,留空自动轮换

多账号模式:

GEMINI_ACCOUNTS=main,backup1
GEMINI_ACCOUNT_MAIN_1PSID=主号 __Secure-1PSID
GEMINI_ACCOUNT_MAIN_PROXY=socks5h://127.0.0.1:10808
GEMINI_ACCOUNT_MAIN_PRIORITY=3

GEMINI_ACCOUNT_BACKUP1_1PSID=备用号 __Secure-1PSID
GEMINI_ACCOUNT_BACKUP1_PROXY=http://127.0.0.1:10809

Docker 环境下代理地址用 http://host.docker.internal:10808docker-compose.yml 已内置映射。

Web 控制台

访问 http://localhost:8787/console,使用 COOKIE_SYNC_TOKEN 登录。

Console

控制台功能:

  • 账号列表:状态、代理、同步时间、健康度
  • 添加 / 编辑 / 删除账号
  • Cookie 更新会先验证,验证失败时保留原有可用 Cookie
  • 账号测试:发送真实对话消息验证可用性
  • 调用记录,方便查看实际情况
  • 代理测试:验证代理连通性

Playground

控制台内置 Playground 聊天界面,支持模型切换、Thinking Level 调节和流式对话测试。

Playground

调用记录

request

调用示例

流式对话

OpenAI 格式

curl http://localhost:8787/openai/v1/chat/completions \
  -H "Content-Type: application/json" \
  -d '{
    "model": "gemini-3.6-flash",
    "stream": true,
    "messages": [{"role": "user", "content": "你好"}]
  }'

Claude 格式

curl http://localhost:8787/claude/v1/messages \
  -H "Content-Type: application/json" \
  -d '{
    "model": "gemini-3.6-flash",
    "stream": true,
    "max_tokens": 1024,
    "messages": [{"role": "user", "content": "你好"}]
  }'

Gemini 原生格式

curl http://localhost:8787/gemini/v1beta/models/gemini-3.6-flash:streamGenerateContent \
  -H "Content-Type: application/json" \
  -d '{
    "contents": [{"parts": [{"text": "你好"}]}]
  }'

三种格式均支持真正的流式输出(real streaming),通过 provider 原生 stream 能力实时转发 delta,无需等待完整响应。

Thinking Level

{
  "model": "gemini-3.6-flash",
  "reasoning_effort": "high",
  "stream": true,
  "messages": [{"role": "user", "content": "详细分析这个问题"}]
}
参数 对应
reasoning_effort low / medium Standard
reasoning_effort high Extended
thinking_level standard / extended 直接映射

文件上传

curl http://localhost:8787/openai/v1/files \
  -H "Authorization: Bearer $COOKIE_SYNC_TOKEN" \
  -F purpose=assistants \
  -F file=@./note.txt

文件 API 使用 COOKIE_SYNC_TOKEN 鉴权。返回 file_id 后在 messages 中引用:

{
  "role": "user",
  "content": [
    {"type": "input_text", "text": "总结这个文件"},
    {"type": "input_file", "file_id": "file-...", "filename": "note.txt"}
  ]
}

Python SDK

from openai import OpenAI

client = OpenAI(base_url="http://localhost:8787/openai/v1", api_key="not-needed")

stream = client.chat.completions.create(
    model="gemini-3.6-flash",
    stream=True,
    messages=[{"role": "user", "content": "你好"}],
)

for chunk in stream:
    if chunk.choices[0].delta.content:
        print(chunk.choices[0].delta.content, end="", flush=True)

模型列表

模型名 说明
gemini-3.6-flash UI 默认 Flash(兼容旧名 gemini-3.5-flash
gemini-3.5-flash-lite UI Flash-Lite(兼容旧名 gemini-3.1-flash-lite
gemini-3.1-pro UI Pro

需要深度思考时使用 Thinking Level 参数,而非依赖模型名后缀。

性能与可靠性

已优化项

优化点 修复前 修复后 影响
流式解析 O(n²) 每个 16KB chunk 全量重扫 512KB 缓冲区 8KB 增量节流,仅在足够新数据到达时重解析 长回复 CPU 开销降低 ~94%
会话读锁竞争 conversationID / IsConversationUntrusted 等用写锁 (Lock) 做纯读操作 改用 RLock / RUnlock,读操作不再互斥 高并发下吞吐量显著提升
Timer GC 压力 流式循环每次迭代 time.NewTimer 循环外创建一次,循环内 Reset 复用 减少 GC 压力和内存分配
HTTP 客户端复用 refreshSessionToken 每次创建新 req.Clienthttp.Client 复用 httpClientrawHTTPClient,连接池保持 减少 TLS 握手,降低刷新延迟
文件上传并行化 多文件串行上传 goroutine 并行上传(并发度 4),保持顺序 多文件场景延迟降低 ~75%
Cookie 缓存原子写 os.WriteFile 非原子,崩溃可能损坏 临时文件 + os.Rename 原子替换 杜绝缓存文件损坏
conversationTo 内存泄漏 map 无限增长 12h TTL 自动清理 长期运行内存稳定
toolBridge/toolPlanner 清理 pruneTranscriptContextsLocked 遗漏这三组 map 补全 TTL 清理 防止上下文缓存内存泄漏
Close() 双关 panic 多次调用 close(stopRefresh) panic sync.Once 保护 杜绝 panic
generateChatID 碰撞 math/rand 可能碰撞 crypto/rand 24 字符 hex 彻底消除碰撞
Claude/Gemini 假流式 先获取完整响应再逐字模拟,首字节延迟极大 调用 provider 原生 stream 接口实时转发 delta 三种格式首字节延迟一致
Claude SSE 格式不规范 仅发送 data: 行,缺少 event: 使用 SendSSEChunk 同时发送 event: + data: 符合 Anthropic API 规范
Claude Index=0 丢失 int + omitempty 导致序列化省略 index=0 改用 *int 指针类型 第一个内容块的 index 正确输出
流式错误检查顺序错误 出错时先发送空内容块再返回错误 出错时直接返回错误,不发送空内容 客户端不再收到误导性空内容
Claude/Gemini 日志静默丢弃 module 未调用 SetLogger,一直使用 NopLogger module 的 RegisterRoutes 注入 logger 错误日志正常输出
Claude controller data race SetLogger 无锁保护 添加 sync.RWMutex 杜绝并发读写竞态

Benchmark 结果

BenchmarkExtractStreamTextFromBuffer-12    256KB buffer    ~4.5ms/op   36-40 MB/s
BenchmarkHasConversationStateRLock-12      1000 entries    20.87 ns/op  0 allocs
BenchmarkPruneConversationsLocked-12       1000 entries    220μs/op
BenchmarkGenerateChatID-12                 crypto/rand     240 ns/op    88 B/op

Docker 部署

快速启动

# 1. 复制环境配置
cp .env.example .env
# 编辑 .env 填写 COOKIE_SYNC_TOKEN 和 Cookie

# 2. 启动服务
docker compose up -d --build

# 3. 查看日志
docker compose logs -f

服务启动后访问:

  • API 端点:http://localhost:8787/openai/v1/chat/completions
  • Web 控制台:http://localhost:8787/console
  • API 文档:http://localhost:8787/docs

配置说明

单账号模式

COOKIE_SYNC_TOKEN=your_secure_token
GEMINI_1PSID=your__Secure_1PSID_cookie
GEMINI_1PSIDTS=your__Secure_1PSIDTS_cookie  # 可选

多账号模式(推荐)

COOKIE_SYNC_TOKEN=your_secure_token
GEMINI_ACCOUNTS=acc1,acc2,acc3

GEMINI_ACCOUNT_ACC1_1PSID=xxx
GEMINI_ACCOUNT_ACC1_PRIORITY=3
GEMINI_ACCOUNT_ACC1_PROXY=http://host.docker.internal:10808

GEMINI_ACCOUNT_ACC2_1PSID=xxx
GEMINI_ACCOUNT_ACC2_PRIORITY=2

网络配置

场景 代理地址写法
宿主机代理 (Windows/Mac) http://host.docker.internal:10808
宿主机代理 (Linux) http://172.17.0.1:10808
容器内 Clash http://clash:7890
无代理 留空

数据持久化

挂载路径 说明 建议
./data Cookie 缓存、账号状态、请求日志 必须持久化
./.env 配置文件(只读挂载) 修改后 docker compose restart 生效
./.cookies Cookie jar 文件 可选

构建特性

  • 多阶段构建:分离编译和运行环境,镜像体积更小
  • BuildKit 缓存:Go 模块缓存挂载,重复构建更快
  • 国内加速:默认使用 GOPROXY=goproxy.cn
  • 静态资源嵌入console.html 通过 go:embed 编入二进制

Admin API

所有 /admin/* 请求需带 Authorization: Bearer <COOKIE_SYNC_TOKEN>

# 列出账号
curl http://localhost:8787/admin/accounts -H "Authorization: Bearer $TOKEN"

# 添加账号
curl -X POST http://localhost:8787/admin/accounts \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer $TOKEN" \
  -d '{"account_id":"acc3","secure_1psid":"...","proxy_url":"..."}'

# 测试账号
curl -X POST http://localhost:8787/admin/accounts/acc1/test -H "Authorization: Bearer $TOKEN"

# 保存 Cookie(202 表示已落盘,账号状态会在后台完成验证)
curl -X POST http://localhost:8787/admin/accounts/acc1/cookies \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer $TOKEN" \
  -d '{"secure_1psid":"...","secure_1psidts":"...","source":"console"}'

# 测试代理
curl -X POST http://localhost:8787/admin/proxy-test \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer $TOKEN" \
  -d '{"proxy_url":"http://host.docker.internal:10808"}'

开发

go test ./...

维护者文档:

说明

本项目基于ntthanh2603/gemini-web-to-api ,后重塑了主要功能,优化了整个请求链路,保留了部分特性。Gemini 网页端结构可能变化,涉及 f.reqx-goog-ext-*c/r/rc/context token 的行为以抓包和回归测试为准。

健康检查与 Kubernetes

  • GET /health 是 liveness,只表示进程存活,适合 Docker Compose,避免 Cookie 暂时失效导致重启循环。
  • GET /ready 是 readiness;至少一个 Gemini 账号健康时返回 200,否则返回 503,并仅包含账号总数、健康数和非敏感状态。
livenessProbe:
  httpGet:
    path: /health
    port: 8787
readinessProbe:
  httpGet:
    path: /ready
    port: 8787

文件存储限制

环境变量 默认值 说明
OPENAI_FILE_MAX_BYTES 33554432 单个上传、Base64 或远程附件最大字节数
OPENAI_FILE_STORE_MAX_BYTES 1073741824 data/openai-files 总容量上限
OPENAI_FILE_TTL_HOURS 24 文件保留小时数;启动和上传前清理过期及孤立文件

About

逆向Gemini网页端,转换成api使用,支持流式和简单工具调用

Topics

Resources

Stars

8 stars

Watchers

1 watching

Forks

Releases

Packages

Contributors

Languages