Gemini API proxy on Vercel Edge.
Overview
is a Gemini API proxy on Vercel (Next.js App Router) for regions where direct Gemini access is slow or blocked, plus a browser streaming playground for debugging. gemini-relay-proxy.vercel.app/chat (demo only) - Prefer DNS in a region that can reach Google Gemini. Do not rely on *.vercel.app in production. If needed, front the service with a jump host or another edge proxy (e.g. CF). - Use Gemini API key. Do not share or reuse others’ keys. - Multiturn messages must end with role: user (or a function response). If the first message is not user, the proxy drops it; if the last is not user, the request is rejected. - Auth paths: /api/v1, /api/v1beta, /api/v1beta2 only. - ?key= or x-goog-api-key with your Gemini key. - headers from PROXY_AUTH_HEADERS; server injects a key from GEMINI_API_KEYS. - Missing credential/path → 401. Proxy mode without GEMINI_API_KEYS → 503. Empty JSON body on POST/PUT/PATCH → 403 (GET needs no body). - Runs on Next.
README
Gemini Relay
Gemini Relay is a Gemini API proxy on Vercel (Next.js App Router) for regions where direct Gemini access is slow or blocked, plus a browser streaming playground for debugging.
Try it: gemini-relay-proxy.vercel.app/chat (demo only)
Important notes
- Custom domain required for production. Prefer DNS in a region that can reach Google Gemini. Do not rely on
*.vercel.appin production. If needed, front the service with a jump host or another edge proxy (e.g. CF). - Use your own Gemini API key. Do not share or reuse others’ keys.
- Multiturn messages must end with
role: user(or a function response). If the first message is notuser, the proxy drops it; if the last is notuser, the request is rejected. - Auth paths:
/api/v1,/api/v1beta,/api/v1beta2only.- Passthrough:
?key=orx-goog-api-keywith your Gemini key. - Proxy mode: headers from
PROXY_AUTH_HEADERS; server injects a key fromGEMINI_API_KEYS. - Missing credential/path →
401. Proxy mode withoutGEMINI_API_KEYS→503. Empty JSON body on POST/PUT/PATCH →403(GET needs no body).
- Passthrough:
- Runs on Next.js App Router Route Handlers (
nodejs+ Fluid Compute):app/api/v1|v1beta|v1beta2/[...path]→services/gemini/. Successful calls return200then stream.maxDurationand business timeout are 120s. - Model IDs live in the URL (transparent forward), e.g.
/api/v1beta/models/{model}:generateContent. Prefer current Stable:gemini-3.5-flash(general) orgemini-3.5-flash-lite(lighter). Playground can Refresh the official model list. - Debug via Vercel → Logs (or local
pnpm devterminal). Playground / MCP are for debugging; generation still goes through the REST proxy.
Deploy
- Clone / import the repo and deploy.
- Attach a custom domain.
- Set env vars (see below). Redeploy after changes.
- If Deployment Protection is on, callers need
x-vercel-protection-bypass(Vercel → Deployment Protection → Protection Bypass for Automation).
Local: copy .env.example → .env, then pnpm install && pnpm dev.
App routes
| Path | Purpose |
|---|---|
/ |
Short how-to |
/chat |
Streaming playground (Settings → API Key → Refresh models → chat) |
/settings |
API Key in browser localStorage only; Base URL fixed to /api/v1beta |
/docs/pass-key |
API guide (passthrough) |
/docs/server-env |
API guide (proxy mode) |
Usage
Replace $HOST with your origin (custom domain in production).
Passthrough (?key=):
curl "$HOST/api/v1beta/models/gemini-3.5-flash:streamGenerateContent?key=$GEMINI_API_TOKEN" \
-H "Content-Type: application/json" \
-H "x-vercel-protection-bypass: $VERCEL_SECRET" \
-H "cache-control: no-cache" \
--data-raw '{"contents":[{"role":"user","parts":[{"text":"Hello Gemini"}]}]}' \
--compressed
Passthrough (header — recommended by Google):
curl "$HOST/api/v1beta/models/gemini-3.5-flash:generateContent" \
-H "Content-Type: application/json" \
-H "x-goog-api-key: $GEMINI_API_TOKEN" \
-H "x-vercel-protection-bypass: $VERCEL_SECRET" \
--data-raw '{"contents":[{"role":"user","parts":[{"text":"Hello Gemini"}]}]}'
Proxy mode (server holds Gemini keys; callers send PROXY_AUTH_HEADERS):
# PROXY_AUTH_HEADERS='{"X-API-KEY":""}'
# GEMINI_API_KEYS='["..."]'
curl "$HOST/api/v1beta/models" \
-H "X-API-KEY: " \
-H "x-vercel-protection-bypass: $VERCEL_SECRET"
Environment variables
| Variable | Where | Description |
|---|---|---|
GEMINI_API_TOKEN |
Client | Your Gemini API key (passthrough). Get it from Google AI Studio / Cloud. |
GEMINI_API_KEYS |
Server | JSON array of Gemini keys for proxy mode. With Vercel KV and ≥2 keys, picks the key with the lowest total tokens for the current UTC day. |
PROXY_AUTH_HEADERS |
Server | JSON object of required headers (e.g. {"X-API-KEY":"..."}). All must match (AND). Names are case-insensitive. |
GEMINI_RELAY_KV_REST_API_URL / GEMINI_RELAY_KV_REST_API_TOKEN |
Server (optional) | Vercel KV REST credentials for rotation counters. Do not use *_READ_ONLY_TOKEN or *_KV_URL / *_REDIS_URL. |
VERCEL_SECRET |
Client (when protection is on) | Value of Protection Bypass for Automation → send as x-vercel-protection-bypass. |
MCP_INSTALL_ENABLED |
Server (optional) | Install MCP (/api/mcp/install). Default true; set false / 0 / off to return 404 after bootstrap. |
MCP (for agents)
Two MCP endpoints share the same Skill docs. Generation stays on REST / Playground.
- Install MCP (public, no secret): read Skill / deploy guide before you have proxy keys.
- After deploy, switch to Auth MCP (proxy headers required): Skill +
gemini_list_models. - Optionally set
MCP_INSTALL_ENABLED=falseto take the install MCP offline.
One-click — Install MCP (no secret):
{
"mcpServers": {
"gemini-relay-install": {
"url": "https://gemini-relay-proxy.vercel.app/api/mcp/install"
}
}
}
Auth MCP (after deploy — replace the secret):
{
"mcpServers": {
"gemini-relay": {
"url": "https://gemini-relay-proxy.vercel.app/api/mcp",
"headers": {
"X-API-KEY": ""
}
}
}
}
| Resource | URL |
|---|---|
| Install MCP | https://gemini-relay-proxy.vercel.app/api/mcp/install |
| Auth MCP | https://gemini-relay-proxy.vercel.app/api/mcp |
| MCP meta | https://gemini-relay-proxy.vercel.app/api/mcp/meta |
| Skill | https://gemini-relay-proxy.vercel.app/skills/gemini-relay-skill.md |
| Skill URI | skill://gemini-relay/gemini-relay-skill.md |
Site UI: header MCP → install + auth one-click / Copy mcp.json. On your host, swap origin to $HOST.
Recommended Tools
Try a different keyword or remove a filter.
Install
npx skillfish add davidkk/vercel-gemini-proxy