gemini-web2api: an OpenAI-compatible endpoint in front of Gemini's web interface
Convert Google Gemini web into OpenAI-compatible API. Zero auth, cross-platform, single file.
At a glance
- What is it?
- A single-file Python server that wraps Gemini's web interface in OpenAI and Google native API shapes, with optional keys, tool calling and a paid-account cookie path for Pro. The catch is that the upstream is a web UI, not an API.
- Who is it for?
- Adopt gemini-web2api if you want an OpenAI-shaped endpoint backed by a Gemini web session and you accept that the upstream is an interface Google does not document or promise. Do not adopt it for anything that must survive an upstream change without warning: the README itself tells you to refresh the xsrf_token when authenticated requests return HTTP 400, which means breakage is expected, not exceptional.
- Can I use it commercially?
- Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
- Is it still maintained?
- Yes. The repository last received commits 35 days ago.
- What is it written in?
- Mainly Python, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on September 17, 2026, and from our analysis. They are not legal advice.
DEEP OPEN-SOURCE ANALYSIS
The problem: Gemini has a web UI, your tooling wants an API
Most editor plugins, chat clients and agent frameworks speak one of two dialects: the OpenAI chat completions shape, or Google's own native model endpoints. Gemini's web interface speaks neither. If you want a Gemini model inside Cherry Studio, ChatBox, the OpenAI Python SDK or Codex CLI, you normally need an API key and a billing relationship. gemini-web2api takes a different route: it sits in front of the web interface and re-exposes it as `/v1/chat/completions`, `/v1/models`, `/v1/responses` and `/v1beta/models`. The intended audience is someone who already has a Gemini web session and wants to reuse it from tools that only know how to talk to an API. The README frames the tradeoff plainly: zero cost, cross-platform, single file. That is the whole pitch, and it is honest about what it is.
How the translation layer is put together
The repository is small enough to read in one sitting: `gemini_web2api.py` at the top level, a `gemini_web2api/` package, a `config.example.json`, a Dockerfile, a `cloudflare/` directory, and a `gemini-cookie-sync-extension/` directory. The package is declared in `pyproject.toml` with no required dependencies at all; `httpx>=0.25` sits in an optional `streaming` extra and in `requirements.txt`. That split is the architecture in miniature. Without httpx the server still answers requests, but streaming is the part that needs it. Requests arrive in OpenAI format, get mapped onto Gemini's web protocol, and the response is mapped back. Two details reveal how thin the abstraction is. First, `gemini_bl` is a build label of the form `boq_assistant-bard-web-server_20260716.08_p0`, a value that tracks the web frontend rather than any published API version. Second, authenticated calls may need an `xsrf_token` that the README says is exposed in the rendered Gemini page source as `SNlM0e` and is sent as the `at` form field. Those are interface-scraping concerns, not API-client concerns, and they are the reason this project needs occasional maintenance in a way an ordinary SDK wrapper does not.
Installing gemini-web2api and sending a first request
The README's quick start is two commands. The first installs httpx, the second starts the server, which listens on `http://localhost:8081/v1`.
pip install httpx
python gemini_web2api.pyConfiguration is a `config.json` next to the script. The example file shows the keys you are expected to touch: `port`, `host`, `retry_attempts`, `retry_delay_sec`, `request_timeout_sec`, `gemini_bl`, `auth_user`, `xsrf_token`, `api_keys`, `cookie_file`, `proxy`, `log_requests` and `temporary_chats`. Leaving `api_keys` empty disables authentication entirely; setting one or more values makes `/v1/*` require `Authorization: Bearer <key>` or `x-api-key: <key>`.
{
"port": 8081,
"host": "0.0.0.0",
"retry_attempts": 3,
"retry_delay_sec": 2,
"request_timeout_sec": 180,
"api_keys": ["sk-your-key"],
"cookie_file": null,
"log_requests": true,
"temporary_chats": false
}With the server running, any OpenAI client works. The README's Python example points the SDK at the local base URL and asks for `gemini-3.5-flash-thinking`, which the model table describes as the extended-thinking variant with the longest output, roughly 20k characters.
from openai import OpenAI
client = OpenAI(base_url="http://localhost:8081/v1", api_key="sk-your-key")
resp = client.chat.completions.create(
model="gemini-3.5-flash-thinking",
messages=[{"role": "user", "content": "Explain quantum computing"}]
)
print(resp.choices[0].message.content)If you would rather not run Python directly, the Dockerfile builds from `python:3.12-slim`, copies the package and the example config, and exposes 8081. The README's run command mounts your config over `/app/config.json`.
cp config.example.json config.json
docker build -t gemini-web2api .
docker run -d --name gemini-web2api -p 8081:8081 -v ./config.json:/app/config.json gemini-web2apiOne behaviour worth knowing before you build on it: `temporary_chats` set to `true` makes the server use Gemini Web temporary chats instead of persisting conversations to account history. If you are pointing this at a personal Google account, that setting is the difference between your test traffic appearing in your chat list and not.
Model names, thinking depth and the Pro cookie problem
The model table mixes real routing choices with naming that will age badly. `gemini-3.6-flash` is described as the all-around latest model, `gemini-3.5-flash` as an alias for it, `gemini-3.5-flash-thinking` as the longest-output variant, `gemini-3.5-flash-thinking-lite` as adaptive depth, `gemini-3.1-pro` as the math and code option that needs a cookie, `gemini-auto` as automatic selection, and `gemini-flash-lite` as the fastest. Thinking depth is adjustable by appending a suffix to the model name, `@think=N`, where 0 is deepest and 4 is shallowest, with 0 as the default. That suffix is a pleasant design: it avoids a separate parameter and it survives clients that only let you type a model string.
The Pro row is where the project's central limitation lives. Anonymous access works for all models, but the README states that `gemini-3.1-pro` routes to Flash without authentication. Getting real Pro routing requires a Gemini Advanced paid subscription cookie, supplied via `--cookie-file cookie.txt` or the `cookie_file` config key. The cookie set listed is `SID`, `HSID`, `SSID`, `APISID`, `SAPISID` and `__Secure-1PSID`, in either a single-line or JSON form. Two consequences follow. A free Google account cookie will authenticate but, per the README, silently fall back to Flash, so you can believe you are on Pro while you are not. And if the signed-in page URL carries an account index such as `/u/1/app/`, you must set `auth_user` to that index, because the wrong value produces HTTP 400 with an `xsrf` error rather than a clear message. The README's remedy is to refresh Gemini Web, update `xsrf_token`, and re-check `auth_user`. That is a manual repair loop, and it is the honest cost of building on a web interface.
Where gemini-web2api is the wrong tool
The README's own notes describe two failure modes rather than hiding them, and both matter more than any feature list. The first is the Docker networking note: if you get empty responses with `content: null` under Docker's default bridge network, the fix is host networking, either `docker run --network host ...` or `network_mode: host`. This is not a configuration nicety. It means a containerised deployment can appear healthy while returning nothing useful. The second is the XSRF path already described, where authenticated requests return HTTP 400 and the fix is a token refresh. If you need an endpoint with a stability commitment, a published versioning policy and a deprecation window, this is the wrong tool, because the thing it wraps is a web frontend whose build label changes and whose token handling is not documented anywhere. The same applies to anything with contractual uptime or data-residency requirements: the request path goes through a browser session tied to a personal account. And if your workload is throughput-heavy, the retry and timeout keys (`retry_attempts`, `retry_delay_sec`, `request_timeout_sec`) suggest a client tuned for interactive use, not batch fan-out. Treat it as a bridge for individual developers and small internal tooling, not as infrastructure.
Alternatives, and how they differ in approach
The obvious alternative is Google's official Gemini API, which gives you a real key, documented endpoints and a stable model naming scheme. The difference is not just price or convenience: it is who owns the contract. With the official API, a model rename is an announcement. Here, a model rename in the web UI is a patch to a table in a README. The second alternative is a dedicated unofficial client library, such as the one the related searches point at with HanaokaYuzu/Gemini-API. That project is a library you import into your own Python code; gemini-web2api is a server you run and point other programs at. If your need is a script that asks Gemini something, a library is less machinery. If your need is Cherry Studio, ChatBox, Codex CLI or the OpenAI Python SDK talking to Gemini without an API key, a library does not help you at all, because those tools will not import your Python. The third path is simply not doing this: use the official API with a free tier key and accept the quota. That is the option to weigh honestly, because it removes the cookie handling, the XSRF refresh and the Docker networking caveat in one step.
Licence, maintenance and what an upgrade actually costs
The project is MIT licensed, declared both in the repository LICENSE file and in `pyproject.toml` as `license = {text = "MIT"}`. MIT is permissive: you can use, modify and redistribute it, including commercially, provided the copyright notice and permission notice are retained. That is the licence text, not legal advice; if you are embedding this in a product, read the LICENSE file and get your own review. The package metadata declares `requires-python = ">=3.8"` and a console script entry point, `gemini-web2api = "gemini_web2api.__main__:main"`, with version 1.1.0.
Maintenance is the part to price in. The last push to the default branch was on 2026-08-14, roughly a month before this writing, and the repository is not archived. Recent releases were not retrieved, so there is no release cadence to point at. What the code itself tells you is that upgrades are not free: `gemini_bl` embeds a dated build label, `xsrf_token` expires and must be pulled from a rendered page, and the model table names versions that will drift as Google renames things. Budget for occasionally re-reading the README rather than assuming a version bump is a drop-in. The `cloudflare/` and `gemini-cookie-sync-extension/` directories also suggest the author expects deployment to involve cookie plumbing outside the Python process, which is another surface to keep working.
Editorial conclusion
Adopt gemini-web2api if you want an OpenAI-shaped endpoint backed by a Gemini web session and you accept that the upstream is an interface Google does not document or promise. Do not adopt it for anything that must survive an upstream change without warning: the README itself tells you to refresh the xsrf_token when authenticated requests return HTTP 400, which means breakage is expected, not exceptional. Before rolling it out, verify three things in your own environment: that gemini-3.5-flash-thinking streams through your client, that tool calling round-trips in the OpenAI format, and whether Docker's default bridge network gives you empty content, in which case the README points at host networking.
Frequently asked questions
What is the Gemini API used for?
In this project's case, the API surface exists so existing OpenAI-compatible clients can talk to Gemini. gemini-web2api exposes `/v1/chat/completions` and `/v1/models` in OpenAI format, plus Google native endpoints under `/v1beta/models` for Gemini CLI and a Responses API at `/v1/responses` for Codex CLI.
How much does the Gemini API cost?
The README describes gemini-web2api as zero cost because it routes through the Gemini web interface rather than a billed API key. The exception is Pro routing: `gemini-3.1-pro` needs a Gemini Advanced paid subscription cookie, otherwise the README says it falls back to Flash.
How much is 1 million tokens in Gemini?
The repository does not price tokens. It reports output sizes in characters instead, for example roughly 20k characters for `gemini-3.5-flash-thinking` and about 12k for `gemini-3.6-flash`, so there is no token accounting to quote.
Are API keys for Gemini free?
gemini-web2api's own keys are not Google keys. The `api_keys` array in `config.json` is optional: when it is empty, authentication is disabled, and when it holds values, `/v1/*` requires `Authorization: Bearer <key>` or `x-api-key: <key>`. You choose those values yourself.
Community notes