Skip to main content

๐Ÿค– gemi โ€” the simplest Python library for Google Gemini web app

Project description

๐Ÿค– gemi

The simplest Python library for Google Gemini โ€” no API key, no asyncio, just your browser cookies.

Python License

from gemi import Gemini

g = Gemini()
print(g.ask("What is the capital of France?"))

โœจ Features

  • No asyncio required โ€” everything works in regular Python scripts
  • Zero-config auth โ€” reads cookies from env vars, .env, JSON file, or browser
  • Simple ask() โ€” returns a Response with .text, .images, .thoughts
  • Streaming โ€” g.stream() yields text as it arrives
  • Multi-turn chat โ€” g.chat() remembers context across messages
  • Gems โ€” create, list, update, and delete system prompt presets
  • Chat management โ€” list, read, and delete your Gemini history
  • Deep Research โ€” g.research("topic") โ†’ full web-browsed report
  • Image generation โ€” g.generate_image("a cat") + .save_images()
  • CLI tool โ€” gemi ask "What is 2+2?"
  • Async support โ€” async_ask(), async_stream() available too

๐Ÿ“ฆ Installation

pip install gemi

With automatic browser cookie detection:

pip install "gemi[browser]"

Requires Python 3.10+


๐Ÿ”‘ Authentication

You need your Gemini session cookies. There are several ways to provide them:

Option A โ€” Environment Variables (recommended)

export GEMINI_PSID="your __Secure-1PSID value"
export GEMINI_PSIDTS="your __Secure-1PSIDTS value"

Or in a .env file in your project directory:

GEMINI_PSID=your_value_here
GEMINI_PSIDTS=your_value_here

Then just use Gemini() โ€” it auto-discovers them.

Option B โ€” Direct

g = Gemini(psid="...", psidts="...")

Option C โ€” JSON Cookie File

g = Gemini(cookies_json="cookies.json")

Supports browser export formats (array of objects, flat dict, {"cookies": [...]} wrapper).

Option D โ€” Auto Browser (needs [browser] extra)

pip install "gemi[browser]"

Just be logged in to gemini.google.com in your browser.

How to get your cookies

  1. Go to gemini.google.com and log in
  2. Press F12 โ†’ Network tab โ†’ refresh the page
  3. Click any request โ†’ Cookies tab
  4. Copy __Secure-1PSID and __Secure-1PSIDTS

๐Ÿš€ Usage

Ask a question

from gemi import Gemini

g = Gemini()

response = g.ask("What is the capital of France?")
print(response.text)   # "Paris"
print(response)        # same โ€” str(response) returns the text

Streaming

for chunk in g.stream("Write a poem about the ocean"):
    print(chunk, end="", flush=True)
print()

Multi-turn Chat

chat = g.chat(model="flash")

chat.say("My name is Alex and I love astronomy.")
reply = chat.say("What books would you recommend for me?")
print(reply)

# View conversation history
for role, text in chat.history:
    print(f"[{role}] {text[:80]}")

# Save to file
chat.save("conversation.txt")

# Keep the chat ID to resume later
print(chat.chat_id)  # โ†’ "c_abc123..."

Resume a Previous Chat

chat = g.resume_chat("c_abc123")
chat.say("Continue from where we left off.")

Attach Files (Images, PDFs, Documents)

response = g.ask(
    "Summarize this document and describe the image",
    files=["report.pdf", "diagram.png"]
)
print(response.text)

Choose a Model

g.ask("Hello!", model="flash")
g.ask("Solve this math problem: ...", model="thinking")
g.ask("Write a detailed essay", model="pro")
Alias Model
flash gemini-3-flash
pro gemini-3-pro
thinking gemini-3-flash-thinking
flash-plus gemini-3-flash-plus
pro-plus gemini-3-pro-plus
thinking-plus gemini-3-flash-thinking-plus
flash-advanced gemini-3-flash-advanced
pro-advanced gemini-3-pro-advanced
thinking-advanced gemini-3-flash-thinking-advanced

Thinking Models

response = g.ask("What is 17 ร— 23?", model="thinking")
print(response.thoughts)  # reasoning steps
print(response.text)      # final answer

Images

# Get web images in a response
response = g.ask("Show me pictures of the Eiffel Tower")
for img in response.web_images:
    print(img.title, img.url)

# Generate AI images
response = g.generate_image("a futuristic city at sunset")
paths = response.save_images("./generated/")
print(paths)  # ['/path/to/generated/gemi_0.png']

# One-liner: generate and auto-save
g.generate_image("a cute robot", save_to="./robots/")

Chat Management

# List recent conversations
for chat in g.list_chats():
    print(chat["id"], chat["title"])

# Read a chat's full history
turns = g.read_chat("c_abc123")
for turn in turns:
    print(f"[{turn['role']}] {turn['text'][:80]}")

# Delete one chat
g.delete_chat("c_abc123")

# Delete multiple chats at once
results = g.delete_chats(["c_abc", "c_def", "c_ghi"])
print(results)  # {'c_abc': True, 'c_def': True, 'c_ghi': True}

Gems (System Prompt Presets)

# List all gems
for gem in g.get_gems():
    kind = "system" if gem["predefined"] else "custom"
    print(f"[{kind}] {gem['name']} โ†’ {gem['id']}")

# Find a specific gem by name
gem = g.get_gem(name="Coding partner")

# Use a gem in a one-shot ask
response = g.ask("Review my code", gem=gem["id"])

# Use a gem in a multi-turn chat
chat = g.chat(gem=gem["id"])
chat.say("Help me write a Python function")

# Create a custom gem
my_gem = g.create_gem(
    name="Python Teacher",
    prompt="You are a patient Python teacher. Explain with simple examples.",
    description="For learning Python",
)
print(my_gem["id"])

# Update a gem
g.update_gem(
    gem_id=my_gem["id"],
    name="Advanced Python Teacher",
    prompt="You are an expert Python engineer. Focus on best practices.",
)

# Delete a gem
g.delete_gem(my_gem["id"])

Deep Research

# One-liner โ€” returns the full report as a string
report = g.research("Impact of large language models on software engineering")
print(report)

# With progress callback and save to file
def show_progress(status):
    print(f"  [{status['state']}]", end="\r", flush=True)

report = g.research(
    "Climate change adaptation strategies 2025",
    timeout=600,
    on_status=show_progress,
)

with open("report.md", "w") as f:
    f.write(report)

List Available Models

for m in g.list_models():
    status = "โœ“" if m["available"] else "โœ—"
    print(f"[{status}] {m['name']}: {m['display_name']}")

# Or just get available names
print(g.models)

Temporary Conversations (not saved to history)

response = g.ask("Secret question", temporary=True)

Context Manager

with Gemini() as g:
    print(g.ask("Hello!"))
# client closes cleanly

Async Usage (for async code / Jupyter notebooks)

import asyncio
from gemi import Gemini

async def main():
    g = Gemini()
    async with g:
        response = await g.async_ask("Hello!")
        print(response.text)

        async for chunk in g.async_stream("Tell me a story"):
            print(chunk, end="", flush=True)

asyncio.run(main())

Account Diagnostics

info = g.inspect()
print("Deep Research:", info["deep_research_available"])
print("Status:", info["account_status"])

๐Ÿ–ฅ๏ธ CLI

After installing you get the gemi command:

# Ask a question
gemi ask "What is quantum entanglement?"

# Stream a response
gemi stream "Write a haiku about code"

# Interactive chat REPL
gemi chat

# Resume an existing chat
gemi chat c_abc123

# List recent conversations
gemi chats

# Read a chat's message history
gemi read c_abc123

# Delete one or more chats
gemi delete c_abc123 c_def456

# List available models
gemi models

# List gems
gemi gems

# Create a custom gem
gemi gem-create --name "Chef" --prompt "You are a master chef."

# Update a gem
gemi gem-update GEM_ID --name "Chef Pro" --prompt "Updated prompt"

# Delete a gem
gemi gem-delete GEM_ID

# Run a deep research task
gemi research "AI trends in 2025" --output report.md

# Check account feature availability
gemi inspect

CLI Authentication

# Via environment variables (recommended)
export GEMINI_PSID="..."
export GEMINI_PSIDTS="..."
gemi ask "Hello"

# Via JSON cookie file
gemi --cookies cookies.json ask "Hello"

# Via direct flags
gemi --psid "..." --psidts "..." ask "Hello"

# Via proxy
gemi --proxy http://127.0.0.1:8080 ask "Hello"

# Enable debug output
GEMINI_DEBUG=1 gemi ask "Hello"

๐Ÿ“ Project Structure

gemi/
โ”œโ”€โ”€ src/
โ”‚   โ””โ”€โ”€ gemi/
โ”‚       โ”œโ”€โ”€ __init__.py     # Public API
โ”‚       โ”œโ”€โ”€ client.py       # Gemini class (main entry point)
โ”‚       โ”œโ”€โ”€ chat.py         # Chat class (multi-turn conversations)
โ”‚       โ”œโ”€โ”€ response.py     # Response wrapper
โ”‚       โ”œโ”€โ”€ cookies.py      # Cookie discovery from multiple sources
โ”‚       โ”œโ”€โ”€ exceptions.py   # Re-exported exceptions
โ”‚       โ””โ”€โ”€ cli.py          # CLI (installed as `gemi` command)
โ”œโ”€โ”€ pyproject.toml
โ”œโ”€โ”€ README.md
โ””โ”€โ”€ LICENSE

โ— Notes

  • Uses browser session cookies โ€” unofficial reverse-engineered API
  • Cookie tokens expire; re-export them if you get an AuthError
  • Deep Research and image generation depend on your Google account type and region
  • Some features require Gemini Advanced (paid subscription)

๐Ÿ“„ License

Apache License 2.0. See LICENSE.

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

gemi-0.1.0.tar.gz (77.3 kB view details)

Uploaded Source

Built Distribution

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

gemi-0.1.0-py3-none-any.whl (85.7 kB view details)

Uploaded Python 3

File details

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

File metadata

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

File hashes

Hashes for gemi-0.1.0.tar.gz
Algorithm Hash digest
SHA256 851e53f4e2c8c9bfd587bf90a712b538fef8dff526ad1d510be39914bee49e57
MD5 2a0d9a1a4a49c37308e3edccfe327049
BLAKE2b-256 3eebbc01a3d5cf60d46f7e3a6322238ea164c3672406f438a617b70016e51d58

See more details on using hashes here.

File details

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

File metadata

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

File hashes

Hashes for gemi-0.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 26f8e2a24c53e7614ddecbf5593ef9c8a89ca7adfb3e375c80b528db106eb221
MD5 818d645ee0f7c528b5c3285a2937853e
BLAKE2b-256 d265a8252a529feefd58671c0ffccb11baad9dd4d5a02feff67ff7e0296348a4

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