Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
41 changes: 36 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,15 +16,16 @@ Convert Google Gemini's web interface into an OpenAI-compatible API. Zero cost,
- **Multiple Models**: Flash (3.6), Extended Thinking (20k+ char output), Pro, Auto, Lite
- **Thinking Depth**: Adjustable via `@think=N` suffix (0=deepest, 4=shallowest)
- **Web Search**: Built-in internet access (Gemini's native search)
- **Cross-Platform**: Pure Python, single optional dependency (`httpx` for streaming)
- **Cross-Platform**: Python service with `curl_cffi` for Chrome-compatible image requests
- **Streaming**: SSE streaming support via `httpx`
- **Codex CLI**: Responses API (`/v1/responses`) for OpenAI Codex integration
- **Gemini CLI**: Google native API (`/v1beta/models`) for Gemini CLI compatibility
- **Image Output**: OpenAI Images and Responses image-generation output with bounded, verified downloads

## Quick Start

```bash
pip install httpx
pip install -r requirements.txt
python gemini_web2api.py
```

Expand Down Expand Up @@ -251,7 +252,10 @@ resp = client.chat.completions.create(
## Image Input

OpenAI-style multimodal messages are supported for Chat Completions and the
Responses API. Use either HTTP(S) image URLs or base64 data URLs:
Responses API. Use either public HTTPS image URLs or base64 data URLs. Remote
images are limited to 10 MiB and three redirects; private, loopback, link-local,
and non-image responses are rejected. Remote image downloads use a direct,
DNS-pinned connection instead of the configured proxy to preserve this boundary.

```python
resp = client.chat.completions.create(
Expand All @@ -266,17 +270,44 @@ resp = client.chat.completions.create(
)
```

## Image Output

`POST /v1/images/generations` accepts a text `prompt`, optional `model`, and `n: 1`.
The `model` field is accepted for client compatibility; Gemini Web selects its image route
independently of the text-model catalog. The endpoint returns one OpenAI-compatible item.
`response_format` defaults to `b64_json`, which
prefers Gemini's full-size RPC URL and falls back to preview when that RPC is unavailable.
Use `url` to return a validated final HTTPS `googleusercontent.com` image URL (text
mediators are resolved without downloading the image bytes).
`stream`, `size`, `quality`, and `style` are intentionally unsupported. The Responses API
also recognizes `{ "type": "image_generation" }` in `tools` and emits one
`image_generation_call` containing base64 output alongside any generated text.

Chat Completions routes explicit requests such as `generate an image of ...` in the latest
user turn through the same image-generation path. It returns a browser-accessible Markdown
image URL, including for streaming clients that send function tools or retain older image
attachments in conversation history. Historical attachments are not treated as image edits.

For base64 output, the server downloads only HTTPS exact/subdomain
`googleusercontent.com` URLs with Chrome impersonation, at most three redirects and 10 MiB.
PNG, JPEG, and WebP bytes and their HTTP content type must agree.
`generated_image_max_bytes` and
`generated_image_max_redirects` in configuration can lower these limits, but cannot raise
the hard 10 MiB / three-redirect caps.

## Limitations

- **Image upload may require cookies**: Multimodal input uses Gemini Web's image upload endpoint. If anonymous upload fails, configure a Gemini cookie.
- **Image requests require `curl_cffi` and may require cookies**: Multimodal input and generated-image output use Chrome-impersonated requests. If upload or generation fails, configure a Gemini cookie. Image input streaming returns one complete result rather than incremental text.
- **Generated image protocol can change**: Image output uses Gemini's undocumented GUI payload and full-size RPC. The server falls back to the validated preview when full-size RPC resolution is unavailable; edits, caching, and proxying are not implemented.
- **Not real Pro/Ultra**: Without a paid subscription cookie, `gemini-3.1-pro` routes to the same Flash model. The "Pro" label is a UI preference, not a backend model switch.
- **Single-turn only**: Each request is an independent conversation. Multi-turn context is simulated by including previous messages in the prompt.
- **Rate limits**: Google may throttle high-frequency requests. The server retries automatically but sustained heavy use may be blocked.

## Requirements

- Python 3.8+
- `httpx` (`pip install httpx`) — used for streaming requests
- `curl_cffi` (`pip install -r requirements.txt`) — required for Gemini image input and output
- `httpx` (`pip install httpx`) — used for text streaming requests
- Network access to `gemini.google.com` (proxy/VPN may be needed in some regions)

## How It Works
Expand Down
36 changes: 31 additions & 5 deletions README_CN.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,15 +16,16 @@
- **多模型**: Flash (3.6), 扩展思考 (2万字+输出), Pro, Auto, Lite
- **思考深度**: 通过 `@think=N` 后缀调节 (0=最深, 4=最浅)
- **联网搜索**: 内置互联网访问 (Gemini 原生搜索能力)
- **跨平台**: Python, 仅一个可选依赖 (`httpx` 用于流式输出)
- **跨平台**: Python 服务,图片请求使用 `curl_cffi` 提供 Chrome 兼容性
- **流式输出**: 基于 `httpx` 的 SSE Streaming 支持
- **Codex CLI**: Responses API (`/v1/responses`) 兼容 OpenAI Codex
- **Gemini CLI**: Google 原生 API (`/v1beta/models`) 兼容 Gemini CLI
- **图片输出**: 支持 OpenAI Images 和 Responses 图片生成输出,并对下载进行边界与格式校验

## 快速开始

```bash
pip install httpx
pip install -r requirements.txt
python gemini_web2api.py
```

Expand Down Expand Up @@ -224,7 +225,9 @@ python gemini_web2api.py
## 图片输入

Chat Completions 和 Responses API 支持 OpenAI 风格的多模态消息。图片可以使用
HTTP(S) URL 或 base64 data URL:
公开 HTTPS URL 或 base64 data URL。远程图片最多 10 MiB、允许 3 次重定向;私有、
回环、链路本地地址以及非图片响应会被拒绝。为固定已验证的 DNS 地址并保持安全边界,
远程图片下载使用直连,不经过配置的代理:

```python
resp = client.chat.completions.create(
Expand All @@ -239,17 +242,40 @@ resp = client.chat.completions.create(
)
```

## 图片输出

`POST /v1/images/generations` 接受文本 `prompt`、可选 `model` 与 `n: 1`。`model`
字段仅用于兼容客户端;Gemini Web 会独立选择图片路由,不使用文本模型目录。
接口返回一个 OpenAI 兼容结果。`response_format` 默认是 `b64_json`,优先使用 Gemini 全尺寸 RPC,
该 RPC 不可用时回退预览图;指定 `url` 时返回已验证的最终 HTTPS
`googleusercontent.com` 图片 URL(仅解析文本中转,不下载图片字节)。`stream`、`size`、`quality` 和
`style` 有意不支持。Responses API 的 `tools` 中也可使用
`{ "type": "image_generation" }`,会在保留文本输出的同时追加一个带 base64 结果的
`image_generation_call`。

Chat Completions 会识别最新用户消息中类似 `generate an image of ...` 的明确图片生成请求,
并使用同一图片生成路径。流式客户端即使携带函数工具或在对话历史中保留旧图片附件,也会
收到浏览器可访问的 Markdown 图片 URL。历史附件不会被当作图片编辑输入。

base64 输出仅使用 Chrome 模拟下载 HTTPS 的精确或子域
`googleusercontent.com` 地址:最多 3 次重定向、10 MiB,且 PNG/JPEG/WebP 文件头必须
与 HTTP Content-Type 一致。配置项 `generated_image_max_bytes` 与
`generated_image_max_redirects` 可以进一步降低限制,
但不能超过硬编码的 10 MiB / 3 次重定向上限。

## 已知限制

- **图片上传可能需要 Cookie**: 多模态输入使用 Gemini 网页端图片上传接口。匿名上传失败时, 请配置 Gemini cookie。
- **图片请求需要 `curl_cffi`,且可能需要 Cookie**: 多模态输入与图片生成输出使用 Chrome 模拟请求。上传或生成失败时,请配置 Gemini cookie。图片输入的流式请求会返回一个完整结果,而非增量文本。
- **图片生成协议可能变化**: 图片输出依赖 Gemini 未公开的 GUI 请求体和全尺寸 RPC。全尺寸 RPC 不可用时会回退到已验证预览图;未实现图片编辑、缓存或代理。
- **Pro/Ultra 非真实路由**: 无付费订阅 cookie 时, `gemini-3.1-pro` 实际路由到 Flash 模型. "Pro" 只是 UI 偏好标签.
- **单轮对话**: 每次请求是独立对话, 多轮上下文通过在 prompt 中包含历史消息模拟.
- **频率限制**: Google 可能限制高频请求, server 会自动重试但持续高负载可能被封.

## 系统要求

- Python 3.8+
- `httpx` (`pip install httpx`) — 用于流式请求
- `curl_cffi` (`pip install -r requirements.txt`) — Gemini 图片输入与输出所需
- `httpx` (`pip install httpx`) — 用于文本流式请求
- 需要能访问 `gemini.google.com` (部分地区需代理)

## 工作原理
Expand Down
4 changes: 3 additions & 1 deletion config.example.json
Original file line number Diff line number Diff line change
Expand Up @@ -14,5 +14,7 @@
"cookie_file": null,
"proxy": null,
"log_requests": true,
"temporary_chats": false
"temporary_chats": false,
"generated_image_max_bytes": 10485760,
"generated_image_max_redirects": 3
}
3 changes: 3 additions & 0 deletions gemini_web2api/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,9 @@
"proxy": None,
"api_keys": [],
"temporary_chats": False,
# Generated image output only; values above the hard safety caps are ignored.
"generated_image_max_bytes": 10 * 1024 * 1024,
"generated_image_max_redirects": 3,
}

CONFIG = dict(DEFAULT_CONFIG)
Expand Down
Loading