Transforms Google Gemini web interface into a standardized REST API.
Access Gemini's power without API keys — just use your cookies!
Created with ❤️ by @ntthanh2603
Note
This project is intended for research and educational purposes only. Please use responsibly and refrain from any commercial use.
Warning
This project is not affiliated with Google. It uses reverse-engineered web cookies and may not comply with Google's Terms of Service. Use at your own risk — the author assumes no responsibility for any account actions or data loss.
Problem: You want to use Google Gemini's latest models, but you don't have an API key or prefer not to use one.
Solution: Creates a local API server that:
- ✅ Connects to Gemini's web interface using your browser cookies
- ✅ Exposes OpenAI / Claude / Gemini-compatible API endpoints
- ✅ No API keys needed — just cookies from your browser
- ✅ Handles authentication and session management automatically
Use Cases:
- Use Gemini without API keys
- Test Gemini integration locally
- Build applications leveraging Gemini's latest models
- Develop with cookie-based authentication
No cloning needed — pull and run directly from the registry.
Step 1 — Get your cookies
Warning
Keep these values secure and never share or commit them — they provide direct access to your Google account.
- Go to gemini.google.com and sign in
- Press
F12→ Network, reload Gemini, and select abatchexecute?rpcids=otAQ7brequest - Copy its complete
Cookierequest header. If the request URL contains an account slot such as/u/2/, also useGEMINI_AUTH_USER="2"below.
Step 2 — Run
docker run -d -p 4981:4981 \
-e GEMINI_COOKIES="your_complete_cookie_header" \
-e GEMINI_AUTH_USER="2" \
-e GEMINI_REFRESH_INTERVAL=30 \
-e GEMINI_MAX_RETRIES=3 \
-e GEMINI_TEMPORARY=false \
-e APP_ENV=production \
-e RATE_LIMIT_ENABLED=true \
-e RATE_LIMIT_WINDOW_MS=60000 \
-e RATE_LIMIT_MAX_REQUESTS=10 \
-v ./cookies:/home/appuser/.cookies \
--tmpfs /tmp:rw,size=512m \
--tmpfs /home/appuser/.cache:rw,size=256m \
--name gemini-web-to-api \
--restart unless-stopped \
ghcr.io/ntthanh2603/gemini-web-to-api:latestDone! Jump to Test it. 🎉
Use this if you want to build for a specific architecture (amd64, arm64, etc.) or modify the source code.
Step 1 — Clone the repository
git clone https://github.com/ntthanh2603/gemini-web-to-api.git
cd gemini-web-to-apiStep 2 — Get your cookies and configure .env
Warning
Keep these values secure and never commit your .env file — it contains credentials that provide access to your Google account.
-
Go to gemini.google.com and sign in
-
Press
F12→ Network, reload Gemini, and select abatchexecute?rpcids=otAQ7brequest -
Copy its complete
Cookierequest header intoGEMINI_COOKIES. -
Match
GEMINI_AUTH_USERto the request URL. For example, use2when the URL contains/u/2/; leave it empty when there is no/u/<number>/. Always take the cookie and account slot from the same browser tab. -
Create your
.envfrom the example:cp .env.example .env
-
Paste the values into
.env:GEMINI_COOKIES=your_complete_cookie_header GEMINI_AUTH_USER=2 GEMINI_REFRESH_INTERVAL=30 GEMINI_MAX_RETRIES=3 GEMINI_TEMPORARY=false APP_ENV=production RATE_LIMIT_ENABLED=true RATE_LIMIT_WINDOW_MS=60000 RATE_LIMIT_MAX_REQUESTS=10
Step 3 — Run
Pick whichever method suits your setup:
| Method | Command | Requirements |
|---|---|---|
| 🐳 Docker Compose | docker compose up -d --build |
Docker |
| 🐹 Go direct | go run cmd/server/main.go |
Go 1.21+ |
| ⚡ Task (dev mode) | task dev |
Task + Air (task install-air) |
task devruns the server with hot reload: Air rebuilds and restarts it whenever a.go,.jsonor.envfile changes (config in.air.toml).
Done! Jump to Test it. 🎉
curl -X POST http://localhost:4981/openai/v1/chat/completions \
-H "Content-Type: application/json" \
-d '{"model": "gemini-advanced", "messages": [{"role": "user", "content": "Hello!"}]}'Your Gemini Web To API is running at http://localhost:4981 🎉
- 🌉 Universal AI Bridge: One server, three protocols (OpenAI, Claude, Gemini)
- 🔌 Drop-in Replacement: Works with existing OpenAI / Claude / Gemini SDKs
- 🔄 Smart Session Management: Auto-rotates cookies to keep sessions alive
- ⚡ High Performance: Built with Go and Fiber for speed
- 🐳 Production Ready: Docker Compose support, Scalar UI, health checks
- 📝 Well Documented: Interactive API docs at
/docs - 🖼️ Image Generation: OpenAI-compatible text-to-image with authenticated
b64_jsonoutput - 🧩 Image Inputs: Remote URLs,
data:URLs and multiple reference images in chat requests - 🎬 Video Generation: Text-to-video (16:9 or 9:16 MP4) via Gemini Web's Videos tool, usable from the OpenAI (
client.videos) and Google GenAI (generate_videos) SDKs - 🧾 Canvas: Gemini Canvas code files and documents via any chat API — just use a
-canvasmodel (e.g.gemini-pro-canvas) - 🎵 Music Generation: Gemini Web's music tool through
client.audio.speech(OpenAI) and-musicmodels (Gemini)
See Image generation and image inputs for tested examples, limitations and security guidance. See Video generation for the video APIs and the OpenAI / Gemini SDK examples. See Canvas and the OpenAI / Gemini / Claude SDK examples for canvas mode. See Music generation and the OpenAI / Gemini SDK examples.
| Variable | Required | Default | Description |
|---|---|---|---|
GEMINI_COOKIES |
✅ Yes | — | Complete Cookie request header copied from the Gemini Web tab |
GEMINI_AUTH_USER |
❌ No | — | Google account slot from the Gemini URL, e.g. 2 for /u/2/app |
GEMINI_REFRESH_INTERVAL |
❌ No | 30 |
Cookie rotation interval (minutes) |
GEMINI_MAX_RETRIES |
❌ No | 3 |
Max retry attempts when an API call fails |
GEMINI_TEMPORARY |
❌ No | false |
Enable stateless/incognito mode for all requests |
PORT |
❌ No | 4981 |
Server port |
RATE_LIMIT_ENABLED |
❌ No | false |
Enable or disable rate limiting |
RATE_LIMIT_WINDOW_MS |
❌ No | 60000 |
Rate limit time window in milliseconds |
RATE_LIMIT_MAX_REQUESTS |
❌ No | 10 |
Maximum number of requests allowed per time window |
- Environment Variables (highest priority)
.envfile- Defaults (lowest priority)
The provider discovers selectable models and their internal IDs from the signed-in account's Gemini Web model registry during session initialization and refresh. List the current choices with:
curl http://localhost:4981/openai/v1/modelsUse a returned model ID in your requests. IDs are derived from Gemini's current
display labels, such as gemini-3.6-flash and gemini-3.1-pro; they are not a
fixed allowlist. Every selectable registry entry is returned, so newly added
Gemini models become available without a code update. Category names returned
by Gemini remain aliases, and gemini-advanced is retained as a compatibility
alias for the discovered Pro category. An unavailable or unknown name returns
an error instead of silently selecting another model.
Model names are not seeded locally. When Google adds, removes, or renames a model, use the names returned by this endpoint instead of relying on old Gemini API version names.
The model field in a completion response contains the resolved versioned
model ID (for example, a gemini-advanced request currently returns
gemini-3.1-pro). Generated self-introductions are ordinary model output and
can still be inaccurate.
Gemini Web may silently serve a lower-tier model after the selected model's
quota is exhausted. The proxy detects an unambiguous different model ID in the
protocol response and reports that model in model. The original caller value
is preserved in requested_model. This keeps the response truthful without
blocking a model that Gemini still advertises as selectable; after its quota
resets, model returns to the requested version.
from openai import OpenAI
client = OpenAI(
base_url="http://localhost:4981/openai/v1",
api_key="not-needed"
)
response = client.chat.completions.create(
model="gemini-advanced",
messages=[{"role": "user", "content": "Hello!"}]
)
print(response.choices[0].message.content)from langchain_anthropic import ChatAnthropic
llm = ChatAnthropic(
base_url="http://localhost:4981/claude",
model="gemini-advanced",
api_key="not-needed"
)
response = llm.invoke("Explain quantum computing")
print(response.content)from google import genai
client = genai.Client(
api_key="not-needed",
http_options={
"base_url": "http://localhost:4981/gemini",
"api_version": "v1beta",
},
)
response = client.models.generate_content(
model="gemini-advanced",
contents="Write a poem about coding",
)
print(response.text)Install the maintained SDK with pip install google-genai. Both regular
generation and generate_content_stream are supported; the latter uses the
SDK's alt=sse transport.
curl -X POST http://localhost:4981/openai/v1/chat/completions \
-H "Content-Type: application/json" \
-d '{
"model": "gemini-advanced",
"messages": [{"role": "user", "content": "What is AI?"}],
"stream": false
}'More examples are available in the examples/ directory.
Once running, visit http://localhost:4981/docs for interactive API documentation powered by Scalar.
Contributions are welcome! Please feel free to submit a Pull Request.
- Fork the repository
- Create your feature branch (
git checkout -b feature/amazing-feature) - Commit your changes (
git commit -m 'Add some amazing feature') - Push to the branch (
git push origin feature/amazing-feature) - Open a Pull Request
- Nguyễn Tuấn Thành (@ntthanh2603)
This project is licensed under the MIT License — see the LICENSE file for details.
If you find this project useful, please consider giving it a star! ⭐
- GitHub: ntthanh2603/gemini-web-to-api
- Gemini Web: gemini.google.com
- Issues: Report a bug
Created with ❤️ by @ntthanh2603

