Model or dataset
ntthanh2603/gemini-web-to-api avatar
ntthanh2603/gemini-web-to-api

gemini-web-to-api: A Cookie-Backed Gemini Proxy That Speaks Three API Dialects

✨Reverse-engineered API for Gemini web app. It can be used as a genuine API key from OpenAI, Gemini, and Claude.

469 stars114 forksGoMIT

At a glance

What is it?
This Go and Fiber server turns a signed-in Gemini web session into OpenAI, Claude, and Gemini compatible HTTP endpoints. It is a research tool with a clear operational cost: your Google session cookie becomes the credential, and the project's own README says it may not comply with Google's terms.
Who is it for?
Adopt it only for local experimentation, protocol translation tests, or internal demos where a Google account you can afford to lose is acceptable. Do not put it behind a public endpoint, do not wire it into production traffic, and do not treat it as a substitute for a paid API key.
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 2 days ago.
What is it written in?
Mainly Go, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on September 15, 2026, and from our analysis. They are not legal advice.

DEEP OPEN-SOURCE ANALYSIS

What gemini-web-to-api actually replaces

The problem it targets is narrow and specific: you want to call a recent Gemini model from code, but you do not have an API key, or you do not want to provision one. The README states this directly, framing the project as a local API server that connects to Gemini's web interface using browser cookies and exposes OpenAI, Claude, and Gemini-compatible endpoints. The intended users are developers testing an integration locally, people building small applications against Gemini's latest models, and anyone experimenting with cookie-based authentication. The README is explicit that the project is for research and educational purposes only and asks users to refrain from commercial use. That sentence is not boilerplate. It is the boundary that determines whether the rest of the tool is appropriate for your situation.

The mechanism: a cookie header standing in for an API key

The architecture is a reverse proxy with a translation layer. You sign in at gemini.google.com, open developer tools, reload, and find a request to batchexecute?rpcids=otAQ7b. You copy that request's complete Cookie header. That header, not a bearer token, is what the server presents upstream. The README notes that if the request URL contains an account slot such as /u/2/, you must also set GEMINI_AUTH_USER to match, and it warns to always take the cookie and the account slot from the same browser tab. That warning matters: the cookie identifies the Google account, the slot identifies which signed-in profile on that account, and a mismatch between the two is a plausible source of confusing authentication failures. On top of the cookie, the server handles session management, described in the feature list as auto-rotating cookies to keep sessions alive, and it re-exposes the result under three route families. The test command in the README posts to /openai/v1/chat/completions with a model name of gemini-advanced, which shows the OpenAI shape is the primary surface. The repository topics list Fiber as the HTTP framework and Go as the language, so the request path is Go and Fiber rather than a Node or Python stack.

Getting it running: two paths and the environment keys that matter

The fastest path is the container. The README gives a docker run invocation that publishes port 4981, sets GEMINI_COOKIES to your copied header, and passes GEMINI_AUTH_USER, GEMINI_REFRESH_INTERVAL, GEMINI_MAX_RETRIES, GEMINI_TEMPORARY, APP_ENV, RATE_LIMIT_ENABLED, RATE_LIMIT_WINDOW_MS, and RATE_LIMIT_MAX_REQUESTS. It also mounts ./cookies at /home/appuser/.cookies and adds tmpfs mounts at /tmp and /home/appuser/.cache, with sizes of 512m and 256m respectively. Those mounts are worth noticing: the container runs as appuser, and the writable paths are deliberately constrained rather than left on the image layer. The image is pulled from ghcr.io/ntthanh2603/gemini-web-to-api:latest. The second path is building from source: clone the repository, copy .env.example to .env, fill in the same keys, then choose between docker compose up -d --build, go run cmd/server/main.go with Go 1.21 or newer, or task dev if Task is installed. The README also points at interactive API documentation served at /docs, which is where you would confirm the exact Claude and Gemini route prefixes, since the README only shows the OpenAI one in a runnable example.

Rate limiting is the only guardrail between your client and your account

The default configuration in the README enables rate limiting with a 60000 millisecond window and a maximum of 10 requests per window. That is a low ceiling, and it is set that way for a reason: every request this server makes is a request made as your signed-in Google account. There is no separate quota to exhaust and no billing dashboard to warn you. The failure mode is account-level, not API-level. The README's own warning block says the project is not affiliated with Google, uses reverse-engineered web cookies, and may not comply with Google's terms of service, adding that the author assumes no responsibility for account actions or data loss. Treat the rate limit keys as the primary safety control rather than a performance tuning knob. If you raise RATE_LIMIT_MAX_REQUESTS because a test suite is throttling, you are trading test speed for exposure on an account you cannot restore through a support ticket. The GEMINI_REFRESH_INTERVAL and GEMINI_MAX_RETRIES settings govern how aggressively the server keeps the session alive, and the same reasoning applies to them.

Where this is the wrong tool

Any workload with a service-level expectation is the wrong fit. The credential is a browser session, and browser sessions expire, get invalidated, and get challenged. The README's mitigation is cookie rotation, which is maintenance, not durability. If your application needs to survive an unattended weekend, this is not the component to depend on. The second wrong case is multi-tenant or shared use. The server holds one cookie set, so every caller shares one identity. There is no per-user attribution and no way to revoke one consumer without rotating the credential for all of them. The third case is anything commercial, which the README rules out in its own note. Beyond that, the material does not document how the three protocol surfaces differ in behaviour. The README claims drop-in compatibility with existing OpenAI, Claude, and Gemini SDKs, but only demonstrates the OpenAI chat completions route. Whether streaming, tool calling, or the image endpoints behave identically across all three dialects is not something the supplied material establishes, and you should not assume it.

Compared with calling a paid API directly

The alternative most readers will weigh is simply obtaining a Gemini API key and calling Google's official endpoint. The difference in approach is not performance, it is where the contract lives. With an official key, the credential is issued by the provider, revocable by you, scoped to a project, and backed by a published quota and terms of service. With gemini-web-to-api, the credential is a cookie you extracted from a browser, the interface is a reverse-engineered web endpoint that Google can change without notice, and the compatibility layer is maintained by one project tracking those changes. That is why the release history matters more here than it would for a library with a stable spec. The recent releases listed are v1.2.11, v1.2.10, and v1.2.9, with the two most recent pushed on the same day and v1.2.11 arriving about a week after them. A burst of patch releases is consistent with a project chasing upstream changes, which is exactly the maintenance shape you would expect from this design. A self-hosted gateway in front of a paid key, such as a LiteLLM proxy, solves a similar routing problem with a provider-issued credential instead of a scraped one. The trade is money for stability.

Licence, maintenance, and what the MIT grant does not cover

The repository is MIT licensed, which permits use, modification, and redistribution with the copyright notice and permission notice preserved. That grant covers the code in this repository. It does not grant anything with respect to Google's service, and the README's own warning about terms of service compliance sits outside the licence entirely. Do not read MIT as permission to point this at a Google account in a way the account holder has not agreed to. On maintenance cost, the practical burden is not the Go code; it is the cookie. Someone has to notice when authentication breaks, re-extract the header from a browser, update GEMINI_COOKIES and possibly GEMINI_AUTH_USER, and restart the container. That is a manual, human-in-the-loop operation with no way to automate the extraction from this project's material. Budget for it as recurring operational work, not a one-time setup step. This is not legal advice; if the compliance question is live for you, that is a conversation with someone qualified to have it.

Editorial conclusion

Adopt it only for local experimentation, protocol translation tests, or internal demos where a Google account you can afford to lose is acceptable. Do not put it behind a public endpoint, do not wire it into production traffic, and do not treat it as a substitute for a paid API key. Before running anything, verify three things yourself: that the cookie header you copied still authenticates against the current Gemini web build, that GEMINI_AUTH_USER matches the /u/<number>/ slot of the same browser tab, and that the rate limits you set in RATE_LIMIT_MAX_REQUESTS are low enough that a runaway client cannot hammer the upstream session.

Official sources

  1. Issues
  2. License: MIT
  3. ntthanh2603/gemini-web-to-api on GitHub
  4. README
  5. Releases
Community notes

Community notes