C# reverse-engineered wrapper for Google Gemini web app.
This project aims to create a C# version of the Python project below: https://github.com/HanaokaYuzu/Gemini-API
Base Version:
- Repository: https://github.com/HanaokaYuzu/Gemini-API
- Commit:
3f2b935420fd688e1ab84d937de2c33a871697c0 - Date: 2026-02-10
- Message: Fix the retry logic for unsaved conversations. (#233)
A C# port of the original Python Gemini API project. Provides an async-first wrapper for the Google Gemini Web API with the following features:
- Persistent Cookies - Automatic cookie management and updates
- Image Generation - Support for image generation and editing
- System Prompts - Customizable prompts using Gems
- Extensions Support - Integration with Gemini extensions
- Streaming Mode - Real-time content generation
- Multi-turn Conversations - Built-in chat session management
- Async - Full .NET async/await support
- .NET 8.0 or higher
- C# 11 or higher
- Valid Google account with Gemini access
This library depends on the following NuGet packages:
| Package | Version | Purpose |
|---|---|---|
| System.Net.Http | 4.3.4 | HTTP communication |
| System.Text.Json | 8.0.0 | JSON serialization/deserialization |
| HttpClientFactory | 1.0.0 | HTTP client factory pattern |
Note: When using the NuGet package, these dependencies are automatically resolved. If you manually reference the DLL files, you'll need to install these dependencies separately in your project.
For detailed installation instructions, see INSTALLATION.md.
Quick summary:
- Build from source:
git cloneanddotnet build - Download from Release (Recommended): Use local NuGet feed or GitHub Packages
- Access https://gemini.google.com and log in
- Open Developer Tools (F12) and navigate to the Network tab
- Refresh the page
- Click on a request and copy the following cookie values:
__Secure-1PSID__Secure-1PSIDTS(optional)
using GeminiWebApi;
using GeminiWebApi.Utils;
Logger.SetLogLevel(Logger.LogLevel.Info);
var client = new GeminiClient(
securePsid: "YOUR_SECURE_1PSID",
securePsidts: "YOUR_SECURE_1PSIDTS"
);
await client.InitializeAsync(timeout: 30);
var response = await client.GenerateContentAsync("Hello World!");
Console.WriteLine(response.Text);
await client.CloseAsync();await foreach (var chunk in client.GenerateContentStreamAsync("Tell me a story"))
{
Console.Write(chunk.TextDelta);
}var chat = client.StartChat();
var response1 = await chat.SendMessageAsync("What is machine learning?");
Console.WriteLine(response1.Text);
var response2 = await chat.SendMessageAsync("Can you give me an example?");
Console.WriteLine(response2.Text);using GeminiWebApi.Constants;
var response = await client.GenerateContentAsync(
"What model are you?",
model: ModelType.Gemini30Flash
);Available Models:
ModelType.Unspecified- Default modelModelType.Gemini30Pro- Gemini 3.0 ProModelType.Gemini30Flash- Gemini 3.0 FlashModelType.Gemini30FlashThinking- Gemini 3.0 Flash Thinking
// Fetch available Gems
var gems = await client.FetchGemsAsync(includeHidden: false);
// Search for a specific Gem
var codingGem = gems.Get(name: "Coding Helper");
// Create a custom Gem
var customGem = await client.CreateGemAsync(
name: "Python Expert",
prompt: "You are an expert Python developer",
description: "Helps with Python programming"
);
// Use Gem in conversation
var chat = client.StartChat(gem: customGem.Id);
var response = await chat.SendMessageAsync("How do I use decorators?");// Generate an image
var response = await client.GenerateContentAsync("Generate an image of a sunset");
// Access images in the response
foreach (var image in response.Images)
{
Console.WriteLine($"Image: {image.Title}");
await image.SaveAsync(path: "./images/", filename: "sunset.png");
}using GeminiWebApi.Exceptions;
try
{
var response = await client.GenerateContentAsync("Hello");
}
catch (AuthenticationException ex)
{
Console.WriteLine($"Authentication failed: {ex.Message}");
}
catch (ModelInvalidException ex)
{
Console.WriteLine($"Invalid model: {ex.Message}");
}
catch (GeminiException ex)
{
Console.WriteLine($"Error: {ex.Message}");
}Control logging output:
using GeminiWebApi.Utils;
Logger.SetLogLevel(Logger.LogLevel.Debug); // Verbose logging
Logger.SetLogLevel(Logger.LogLevel.Info); // Info level
Logger.SetLogLevel(Logger.LogLevel.Warning); // Warnings only
Logger.SetLogLevel(Logger.LogLevel.Error); // Errors onlyThe main class for interacting with the Gemini API.
Methods:
InitializeAsync()- Initialize the clientGenerateContentAsync()- Generate content from a promptGenerateContentStreamAsync()- Generate content with streamingStartChat()- Create a new chat sessionFetchGemsAsync()- Retrieve available GemsCreateGemAsync()- Create a custom GemCloseAsync()- Close and clean up the client
Represents a conversation session.
Methods:
SendMessageAsync()- Send a message in the chatSendMessageStreamAsync()- Send a message with streamingChooseCandidate()- Select a specific response candidate
The result of content generation.
Properties:
Text- The complete generated textTextDelta- New text since the last chunk (for streaming)Thoughts- Model's thinking process (when available)Images- List of images in the response
GeminiWebApiDotnet/
├── src/GeminiWebApi/
│ ├── Constants/ # API constants and endpoints
│ ├── Exceptions/ # Custom exceptions
│ ├── Models/ # Data models
│ ├── Utils/ # Utility functions
│ └── GeminiClient.cs # Main client class
├── example/ # Sample usage
├── tests/ # Unit tests
├── GeminiWebApi.csproj # Project file
└── ReadMe.md
AGPL-3.0 License - See the LICENSE file for details
This project is a reverse-engineered implementation and is not affiliated with Google. Use at your own risk and in compliance with Google's Terms of Service.
For Japanese documentation, see ReadMe.ja.md