Skip to main content

Programmatic access to Google Gemini via web UI automation

Project description

๐Ÿค– Gemini Web UI Automation

Programmatic access to Google Gemini โ€” for free. No API key required.

Python 3.10+ License: MIT Playwright

Send prompts ยท Get responses ยท Model selection ยท Multi-turn conversations ยท Session persistence ยท Headless mode


โœจ Features

  • Free access โ€” Uses the Gemini web UI, no API key or billing required
  • Model selection โ€” Switch between Fast, Thinking, and Pro models
  • Async & Sync APIs โ€” Use GeminiClient (async) or GeminiClientSync (sync)
  • Easy auth โ€” Log in via your regular browser cookies, no manual sign-in needed
  • Session persistence โ€” Log in once, reuse the session across runs
  • Headless mode โ€” Run without a display after initial setup
  • Anti-detection โ€” System Chrome + stealth measures to bypass automation detection
  • Multi-turn conversations โ€” Continue chats or start new ones
  • Response streaming detection โ€” Waits for the full response automatically

๐Ÿ“ฆ Installation

# Clone the repo
git clone <your-repo-url>
cd gemini-api-again

# Install the package
pip install -e .

# Install Playwright browsers (first time only)
playwright install chromium

# Optional: Install cookie extraction support
pip install -e ".[cookies]"

Note: You also need Google Chrome installed on your system. The library uses your system Chrome to avoid Google's "browser not secure" detection.

# Ubuntu/Debian
sudo apt install google-chrome-stable

๐Ÿš€ Quick Start

Option A โ€” Login from your browser (easiest, no manual sign-in)

Extract cookies from your regular browser โ€” no Playwright sign-in window needed:

# Install cookie extraction support
pip install -e ".[cookies]"
import asyncio
from gemini_webui import GeminiClient

async def main():
    async with GeminiClient(headless=True, session_path="sessions/default.json") as client:
        # Extract cookies from Chrome โ€” you must be logged into
        # gemini.google.com in your Chrome browser
        await client.login_from_browser(browser_name="chrome")

        response = await client.send_prompt("Explain quantum computing in 3 sentences")
        print(response.text)

asyncio.run(main())

Supported browsers: "chrome", "chromium", "firefox", "opera", "edge"

Option B โ€” Manual login via Playwright browser window

Run this once to log in and save your session. A Chrome window opens โ€” sign in with your Google account:

import asyncio
from gemini_webui import GeminiClient

async def setup():
    async with GeminiClient(headless=False, session_path="sessions/default.json") as client:
        await client.login()  # Browser opens โ€” log in manually
        # Session saved automatically on exit

asyncio.run(setup())

After that, use headless mode with the saved session:

async with GeminiClient(headless=True, session_path="sessions/default.json") as client:
    await client.login()
    response = await client.send_prompt("Explain quantum computing in 3 sentences")
    print(response.text)

Output:

Quantum computing is a revolutionary technology that uses the principles of quantum
mechanics to process information in ways traditional computers cannot. Instead of
standard bits that represent either a 0 or a 1, quantum computers use qubits, which
can exist as both 0 and 1 simultaneously thanks to a property called superposition.
This unique ability allows them to perform complex calculations at unprecedented speeds.

Sync API (simpler, no async/await)

from gemini_webui import GeminiClientSync

with GeminiClientSync(headless=True, session_path="sessions/default.json") as client:
    # Option A: From browser cookies
    client.login_from_browser(browser_name="chrome")

    # Option B: From saved session
    # client.login()

    response = client.send_prompt("What is the meaning of life?")
    print(response.text)

๐Ÿ”„ Model Selection

Switch between Gemini models โ€” Fast (Flash), Thinking, and Pro:

from gemini_webui import GeminiClientSync

with GeminiClientSync(headless=True, session_path="sessions/default.json") as client:
    client.login()

    # List available models
    models = client.list_models()
    print(models)  # ['Fast', 'Thinking', 'Pro']

    # Check current model
    print(client.get_current_model())  # 'Fast'

    # Switch to Pro for advanced tasks
    client.set_model("pro")
    response = client.send_prompt("Solve: integral of x^2 * e^x dx")
    print(response.text)

    # Switch to Thinking for complex reasoning
    client.set_model("thinking")
    response = client.send_prompt("What is 15! / (3! * 5! * 7!)?")
    print(response.text)

    # Switch back to Fast for quick answers
    client.set_model("fast")
Model Alias Description
Fast "fast", "flash" Quick answers (Gemini Flash)
Thinking "thinking" Solves complex problems with reasoning
Pro "pro" Advanced math and code (Gemini Pro)

๐Ÿ’ฌ Multi-Turn Conversations

from gemini_webui import GeminiClientSync

with GeminiClientSync(headless=True, session_path="sessions/default.json") as client:
    client.login()
    client.new_chat()  # Start a fresh conversation

    # First message
    r1 = client.send_prompt("Tell me about Python in 2 sentences")
    print(r1.text)

    # Follow-up โ€” continues in the same conversation
    r2 = client.send_prompt("What are its main advantages?")
    print(r2.text)

    # Start a completely new conversation
    r3 = client.send_prompt("What is Rust?", new_chat=True)
    print(r3.text)

๐ŸŽ›๏ธ Configuration

client = GeminiClient(
    headless=True,              # Run browser in headless mode
    timeout=120.0,              # Response wait timeout (seconds)
    session_path="sessions/default.json",  # Session persistence path
    browser_type="chromium",    # Browser engine (ignored if use_system_chrome=True)
    slow_mo=0,                  # Slow down actions by N ms (debugging)
    request_delay=1.0,          # Min seconds between prompts (avoid rate limits)
    use_system_chrome=True,     # Use system Chrome (avoids detection)
    user_data_dir=None,         # Persistent browser profile directory
)

๐Ÿ“– API Reference

GeminiClient (async)

Method Description
GeminiClient(**kwargs) Create a new client. See Configuration for all options.
async start() Start the browser
async close() Close the browser and save session
async login(session_path=None, login_timeout=120) Authenticate via Playwright browser window
async login_from_browser(browser_name="chrome", session_path=None) Authenticate by extracting cookies from your browser
async send_prompt(prompt, *, new_chat=False) โ†’ GeminiResponse Send a prompt and get a response
async new_chat() Start a new conversation
async set_model(model) Switch model ("fast", "thinking", "pro")
async get_current_model() โ†’ str Get the currently selected model name
async list_models() โ†’ list[str] List available model names
is_authenticated bool โ€” Check if logged in

Supports async with context manager.

GeminiClientSync (sync)

Same API as GeminiClient but without async/await. Supports with context manager.

GeminiResponse

Field Type Description
text str The full response text
prompt str The original prompt sent
conversation_id str | None Conversation identifier from the URL
model str | None Model name (if detectable)
timestamp datetime When the response was received
response = client.send_prompt("Hello")
print(response.text)             # "Hi! How can I help you today?"
print(response.prompt)           # "Hello"
print(response.conversation_id)  # "6ea876188b87661c"
print(response.timestamp)        # 2026-05-09 08:43:01
str(response)                    # "Hi! How can I help you today?"

Exceptions

Exception Description
AuthenticationError Not logged in or session expired
CaptchaError CAPTCHA challenge detected
RateLimitError Google rate limiting detected
ResponseTimeoutError Response not received within timeout
SelectorNotFoundError UI element not found (UI may have changed)
BrowserError Browser launch or runtime error

๐Ÿ” Authentication Methods

Method 1: login_from_browser() โ€” Extract cookies from your browser

The easiest way to authenticate. Extracts Google cookies from your regular browser and injects them into the Playwright context.

Requirements:

pip install -e ".[cookies]"

Prerequisites:

  • You must be logged into gemini.google.com in your chosen browser
  • Your browser must be closed (cookie files are locked while the browser is running)

Usage:

async with GeminiClient(headless=True, session_path="sessions/default.json") as client:
    await client.login_from_browser(browser_name="chrome")
    # Session is saved โ€” next time you can just use login()

Supported browsers: "chrome", "chromium", "firefox", "opera", "edge"

Method 2: login() โ€” Manual sign-in via Playwright window

Opens a Chrome window where you sign in manually. Works in headed mode only.

First time:

async with GeminiClient(headless=False, session_path="sessions/default.json") as client:
    await client.login()  # Sign in manually in the browser window

After that:

async with GeminiClient(headless=True, session_path="sessions/default.json") as client:
    await client.login()  # Uses saved session โ€” no manual sign-in needed

๐Ÿ›ก๏ธ Anti-Detection

Google blocks sign-in from browsers it detects as automated. This library uses several strategies to bypass that:

Strategy How
System Chrome Uses your installed Chrome instead of Playwright's bundled Chromium
Persistent profile Real user data directory โ€” looks like a normal browser
Stealth args --disable-blink-features=AutomationControlled and others
JS patching Removes navigator.webdriver flag
Realistic UA Standard Chrome user agent string

If you still get "This browser or app may not be secure"

  1. Use login_from_browser() โ€” This bypasses the sign-in entirely by using your existing browser cookies
  2. Install Google Chrome (not Chromium) โ€” Google is more lenient with its own browser
  3. Use a persistent user data directory โ€” Makes the browser look like a regular user's:
    client = GeminiClient(
        headless=False,
        session_path="sessions/default.json",
        user_data_dir="/home/you/.config/gemini-automation-chrome",
    )
    

๐Ÿ”ง Troubleshooting

Problem Solution
"This browser or app may not be secure" Use login_from_browser() instead, or see Anti-Detection
"No Google cookies found in chrome" Log into gemini.google.com in your browser first, then close the browser
"Not logged in and running in headless mode" Run with headless=False first, or use login_from_browser()
"CAPTCHA challenge detected" Run with headless=False to solve it manually
"Rate limit detected" Increase request_delay (e.g., 3.0) and wait before retrying
"Response did not complete within timeout" Increase timeout (e.g., 300.0)
"No element found for any selector" The Gemini UI changed โ€” update selectors in src/gemini_webui/selectors.py

๐Ÿ—๏ธ How It Works

โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”     โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”     โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
โ”‚  Your Code   โ”‚โ”€โ”€โ”€โ”€โ–ถโ”‚ GeminiClient โ”‚โ”€โ”€โ”€โ”€โ–ถโ”‚  Chrome Browser  โ”‚
โ”‚              โ”‚     โ”‚              โ”‚     โ”‚  (System Chrome)  โ”‚
โ”‚ send_prompt()โ”‚     โ”‚  โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”  โ”‚     โ”‚                  โ”‚
โ”‚ new_chat()   โ”‚     โ”‚  โ”‚ Auth   โ”‚  โ”‚     โ”‚  gemini.google   โ”‚
โ”‚ login()      โ”‚     โ”‚  โ”‚Manager โ”‚  โ”‚     โ”‚     .com/app     โ”‚
โ”‚              โ”‚     โ”‚  โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜  โ”‚     โ”‚                  โ”‚
โ”‚              โ”‚โ—€โ”€โ”€โ”€โ”€โ”‚  โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”  โ”‚โ—€โ”€โ”€โ”€โ”€โ”‚  Response Text   โ”‚
โ”‚              โ”‚     โ”‚  โ”‚Responseโ”‚  โ”‚     โ”‚                  โ”‚
โ”‚              โ”‚     โ”‚  โ”‚Parser  โ”‚  โ”‚     โ”‚                  โ”‚
โ”‚              โ”‚     โ”‚  โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜  โ”‚     โ”‚                  โ”‚
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜     โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜     โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
                           โ”‚
                    โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”€โ”€โ”€โ”
                    โ”‚   Session    โ”‚
                    โ”‚  Persistence โ”‚
                    โ”‚ (cookies +   โ”‚
                    โ”‚  localStorage)โ”‚
                    โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
  1. Browser launch โ€” Starts system Chrome with a persistent profile and stealth arguments
  2. Authentication โ€” Either extract cookies from your browser (login_from_browser()) or sign in manually (login())
  3. Prompt sending โ€” Types into the contenteditable prompt area and clicks send
  4. Response detection โ€” Monitors the "Stop generating" button + content stability to detect when streaming is complete
  5. Text extraction โ€” Pulls the response text from the model's response container

โš ๏ธ Limitations

  • Text prompts only โ€” No file/image uploads (yet)
  • UI changes โ€” Google may update the Gemini UI, breaking selectors. The library uses fallback selector chains for resilience.
  • Rate limits โ€” Google may throttle excessive usage. Use request_delay to pace requests.
  • Terms of Service โ€” Automating the web UI may violate Google's ToS. Use responsibly.

๐Ÿ› ๏ธ Development

# Install in development mode
pip install -e ".[dev]"

# Run linter
ruff check src/

# Format code
ruff format src/

๐Ÿ“„ License

MIT

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

gemini_webui-0.1.0.tar.gz (46.7 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

gemini_webui-0.1.0-py3-none-any.whl (38.6 kB view details)

Uploaded Python 3

File details

Details for the file gemini_webui-0.1.0.tar.gz.

File metadata

  • Download URL: gemini_webui-0.1.0.tar.gz
  • Upload date:
  • Size: 46.7 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.10.12

File hashes

Hashes for gemini_webui-0.1.0.tar.gz
Algorithm Hash digest
SHA256 babf3c8e11b9c3aa0b3a65cfd6c9bd6a23fd6f74b1a7796a93c060eb328d831c
MD5 4ccbcbbd91af31b6dd75eff90506661c
BLAKE2b-256 0185565f062375b0083e3d584a9efdb1579fa1a33a09e0f80bd062b9495f58e5

See more details on using hashes here.

File details

Details for the file gemini_webui-0.1.0-py3-none-any.whl.

File metadata

  • Download URL: gemini_webui-0.1.0-py3-none-any.whl
  • Upload date:
  • Size: 38.6 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.10.12

File hashes

Hashes for gemini_webui-0.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 2294b2308961e8a5cee5af3934cd0991fc582818c34366122c45992df81f7c34
MD5 c2a107ea222af4812a06ed303e5cffb6
BLAKE2b-256 e7237783f4901d42884a96d0af4015574464ff3bf0ffd296817af1433a2b4188

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page