Package Exports
- gemini-reverse
- gemini-reverse/index.js
This package does not declare an exports field, so the exports above have been automatically detected and optimized by JSPM instead. If any package subpath is missing, it is recommended to post an issue to the original package (gemini-reverse) to support the "exports" field. If that is not possible, create a JSPM override to customize the exports field for this package.
Readme

Gemini-Reverse
An unofficial Node.js client for gemini.google.com, inspired by Gemini-API — a Python reverse engineering project by @HanaokaYuzu.
This package ports the core concepts and functionality of the original Python library to Node.js, with full CommonJS and TypeScript support.
Features
- Send messages and receive responses from Gemini
- Streaming support with text deltas
- Multi-turn chat sessions with conversation history
- File and image upload support
- Gem (system prompt) management — create, update, delete, fetch
- Auto cookie refresh to keep sessions alive
- TypeScript type declarations included
- Proxy support
Installation
npm install gemini-reverseAuthentication
This package uses browser cookies to authenticate with Gemini. You need to obtain your __Secure-1PSID cookie from your browser after logging in to gemini.google.com.
Steps:
- Open gemini.google.com in your browser and log in
- Open DevTools → Application → Cookies →
https://gemini.google.com - Copy the value of
__Secure-1PSID(and optionally__Secure-1PSIDTS)
__Secure-1PSIDTSis optional — the client will attempt to refresh and cache it automatically after the first successful init.
Quick Start
const { GeminiClient } = require('gemini-core');
const client = new GeminiClient({
secure_1psid: 'YOUR_SECURE_1PSID',
});
await client.init();
const chat = client.startChat();
const response = await chat.sendMessage({ prompt: 'Hello, Gemini!' });
console.log(response.text);Usage
Initialize Client
const client = new GeminiClient({
secure_1psid: 'YOUR_SECURE_1PSID',
secure_1psidts: 'YOUR_SECURE_1PSIDTS', // optional
proxy: 'http://host:port', // optional
});
await client.init({
timeout: 300000, // request timeout in ms, default 300000
autoClose: false, // auto close client after inactivity
closeDelay: 300000, // inactivity delay before closing in ms
autoRefresh: true, // auto refresh cookies in background
refreshInterval: 540000 // cookie refresh interval in ms
});Generate Content (single turn)
const response = await client.generateContent({ prompt: 'What is the capital of France?' });
console.log(response.text);Streaming
for await (const chunk of client.generateContentStream({ prompt: 'Tell me a long story.' })) {
process.stdout.write(chunk.text_delta);
}Chat Session
const chat = client.startChat({ model: 'gemini-3.1-pro' });
const res1 = await chat.sendMessage({ prompt: 'My name is Alice.' });
console.log(res1.text);
const res2 = await chat.sendMessage({ prompt: 'What is my name?' });
console.log(res2.text); // remembers contextStreaming in Chat
const chat = client.startChat({ model: 'gemini-3.0-flash' });
for await (const chunk of chat.sendMessageStream({ prompt: 'Explain quantum computing.' })) {
process.stdout.write(chunk.text_delta);
}Temporary Chat (no history saved)
const chat = client.startChat();
const response = await chat.sendMessage({ prompt: 'This will not appear in history.', temporary: true });Send with Files
const chat = client.startChat();
const response = await chat.sendMessage({
prompt: 'Describe this image.',
files: ['./photo.jpg'],
});
console.log(response.text);Multiple Candidates
const chat = client.startChat();
const response = await chat.sendMessage({ prompt: 'Give me a poem.' });
// list all candidates
response.candidates.forEach((c, i) => console.log(`[${i}] ${c.text}`));
// choose a specific candidate to continue the conversation
chat.chooseCandidate(1);Models
// use model name string
const chat = client.startChat({ model: 'gemini-3.1-pro' });
// or use the Model constant
const { Model } = require('gemini-api');
const chat = client.startChat({ model: Model.G_3_0_FLASH });
// or use a custom model dict
const chat = client.startChat({
model: {
model_name: 'my-model',
model_header: { 'x-goog-ext-525001261-jspb': '...' },
},
});Available models:
| String | Constant |
|---|---|
gemini-3.1-pro |
Model.G_3_1_PRO |
gemini-3.0-flash |
Model.G_3_0_FLASH |
gemini-3.0-flash-thinking |
Model.G_3_0_FLASH_THINKING |
unspecified (default) |
Model.UNSPECIFIED |
Images
Responses may include web images or AI-generated images.
const response = await chat.sendMessage({ prompt: 'Send me an image of a cat.' });
for (const img of response.images) {
console.log(img.url, img.title, img.alt);
await img.save({ path: './downloads', verbose: true });
}Read Chat History
const turns = await client.readChat('c_YOUR_CHAT_ID');
for (const turn of turns) {
console.log('User:', turn.user_prompt);
console.log('Gemini:', turn.assistant_response);
}Delete Chat
await client.deleteChat('c_YOUR_CHAT_ID');Gems
// fetch all gems
const gems = await client.fetchGems();
// get by name
const gem = gems.get({ name: 'Coding partner' });
// filter user-created gems
const myGems = gems.filter({ predefined: false });
// use a gem in chat
const chat = client.startChat({ gem: gem });
// create a gem
const newGem = await client.createGem({
name: 'My Assistant',
prompt: 'You are a helpful assistant that speaks formally.',
description: 'Formal assistant gem',
});
// update a gem
await client.updateGem({
gem: newGem,
name: 'My Assistant v2',
prompt: 'You are a helpful assistant that speaks casually.',
});
// delete a gem
await client.deleteGem(newGem);Close Client
await client.close();TypeScript
This package includes full TypeScript declarations out of the box.
import { GeminiClient, ChatSession, ModelOutput, ConversationTurn, Gem, Model } from 'gemini-api';
const client = new GeminiClient({ secure_1psid: '...' });
await client.init();
const chat: ChatSession = client.startChat({ model: 'gemini-3.1-pro' });
const response: ModelOutput = await chat.sendMessage({ prompt: 'Hello!' });
console.log(response.text);Project Structure
gemini-api/
├── index.js # entry point
├── index.d.ts # TypeScript declarations
├── client.js # GeminiClient + ChatSession
├── constants.js # Endpoint, GRPC, Headers, Model, ErrorCode
├── exceptions.js # custom error classes
├── types/
│ ├── candidate.js
│ ├── conversation.js
│ ├── gem.js
│ ├── grpc.js
│ ├── image.js
│ └── modeloutput.js
├── utils/
│ ├── accessToken.js
│ ├── parsing.js
│ ├── rotate.js
│ └── upload.js
└── components/
├── chatMixin.js
└── gemMixin.jsError Handling
const {
AuthError,
APIError,
GeminiError,
TimeoutError,
UsageLimitExceeded,
ModelInvalid,
TemporarilyBlocked,
} = require('gemini-api');
try {
const response = await chat.sendMessage({ prompt: 'Hello!' });
} catch (e) {
if (e instanceof AuthError) {
console.error('Cookie expired or invalid.');
} else if (e instanceof UsageLimitExceeded) {
console.error('Usage limit reached. Try again later or switch models.');
} else if (e instanceof TemporarilyBlocked) {
console.error('IP temporarily blocked. Try using a proxy.');
} else if (e instanceof TimeoutError) {
console.error('Request timed out.');
} else if (e instanceof ModelInvalid) {
console.error('Invalid or unavailable model.');
} else if (e instanceof APIError) {
console.error('API error:', e.message);
}
}Credits
Inspired by Gemini-API by @HanaokaYuzu — an unofficial Python client for Gemini through reverse engineering.
Disclaimer
This is an unofficial package and is not affiliated with or endorsed by Google. Use at your own risk. Cookie-based authentication may break if Google changes its internal API.
License
MIT