unlock-perplexity
v1.1.1
Published
Unofficial pure Node.js library to use Perplexity AI without an API key, using your personal account session.
Maintainers
Readme
unlock-perplexity
An unofficial Node.js library to interact with Perplexity AI — no official API key required.
Uses your personal Perplexity account (Free or Pro) via its internal socket.io API. It handles login automatically, captures your session, and sends queries using a browser-impersonated TLS connection to bypass Cloudflare protection.
Features
- 🔐 Interactive login — opens a browser window, no manual token hunting needed
- 💾 Session persistence — logs in once, re-uses the session across runs
- 🍎 Mac App auto-detection — reads token directly from the Perplexity Mac app
- 🛡️ Cloudflare bypass — uses
curl_cffiwith Chrome TLS impersonation - 📡 Streaming support — real-time progress callbacks as Perplexity types its answer
- 🎓 Multiple search modes — internet, scholar, Reddit, YouTube, Wolfram, and more
- 🔧 Full programmatic control — manage tokens, sessions, and queries in code
Prerequisites
| Requirement | Version | |-------------|---------| | Node.js | 18+ | | Python | 3.10+ |
Python is used internally for the curl_cffi browser-impersonation layer. It is set up automatically on install.
Installation
npm install unlock-perplexitynpm install automatically creates a local Python virtual environment and installs curl_cffi. No global Python packages are touched.
Quick Start
const { PerplexityApp } = require('unlock-perplexity');
async function main() {
const app = new PerplexityApp();
// First run: opens browser for login. Subsequent runs: uses saved session.
const result = await app.ask("What is the speed of light?");
console.log(result.answer);
// → "The speed of light in a vacuum is approximately 299,792,458 metres..."
}
main();API Reference
new PerplexityApp(token?, options?)
Creates a new instance. Automatically discovers a session token using this priority:
- Token passed directly as first argument
- Token saved at
~/.perplexity_session(from a previous login) - Token from the Perplexity Mac desktop app
PERPLEXITY_TOKENenvironment variable- Interactive browser login (triggered automatically when
ask()is called)
| Parameter | Type | Default | Description |
|-----------|------|---------|-------------|
| token | string \| null | null | Provide a token directly to skip auto-discovery |
| options.silent | boolean | false | Suppress info log messages |
// Auto-mode (recommended)
const app = new PerplexityApp();
// With explicit token
const app = new PerplexityApp("eyJhbGciOiJIUzI1NiJ9...");
// Silent mode (no console output from the library)
const app = new PerplexityApp(null, { silent: true });app.ask(prompt, onProgress?, queryOptions?)
Sends a prompt to Perplexity and returns the response. Triggers login() automatically if no session exists.
| Parameter | Type | Default | Description |
|-----------|------|---------|-------------|
| prompt | string | required | The question or message to send |
| onProgress | function \| null | null | Callback fired with the growing answer string during streaming |
| queryOptions.mode | string | 'concise' | Response mode: 'concise' or 'copilot' |
| queryOptions.search_focus | string | 'internet' | One of: 'internet', 'scholar', 'writing', 'wolfram', 'youtube', 'reddit' |
Returns: Promise<{ answer: string, web_results: Array, structured_answer: Array }>
// Basic
const result = await app.ask("Explain transformers in ML");
console.log(result.answer);
// With streaming callback
const result = await app.ask("Write a poem about the ocean", (partial) => {
process.stdout.write(partial);
});
// Academic search
const result = await app.ask("Recent papers on LLM reasoning", null, {
search_focus: 'scholar',
mode: 'copilot'
});
// Reddit opinions
const result = await app.ask("Best mechanical keyboards 2024", null, {
search_focus: 'reddit'
});app.login()
Manually triggers the interactive login flow. Opens a Chromium browser window to https://www.perplexity.ai/login. After you sign in, the session token is captured and saved automatically.
If the window is closed without signing in, it falls back to a terminal prompt to paste the token manually.
await app.login();app.isLoggedIn()
Returns true if a session token is currently loaded.
if (!app.isLoggedIn()) {
await app.login();
}app.getToken()
Returns the current session token string, or null.
const token = app.getToken();
console.log(token); // "eyJhbGci..."app.setToken(token, persist?)
Manually set a session token, optionally saving it to disk.
| Parameter | Type | Default | Description |
|-----------|------|---------|-------------|
| token | string | required | The session token to set |
| persist | boolean | true | Save to ~/.perplexity_session |
app.setToken("eyJhbGciOiJIUzI1NiJ9...");app.logout(clearFromDisk?)
Clears the session token from memory and optionally deletes the saved session file.
app.logout(); // Clears token + deletes file
app.logout(false); // Only clears from memoryUtility Functions
These are exported for advanced use cases:
getMacToken()
Reads the session token from the Perplexity Mac App preferences. Returns null on non-macOS systems.
const { getMacToken } = require('unlock-perplexity');
const token = getMacToken();getSavedToken()
Reads the token saved at ~/.perplexity_session.
const { getSavedToken } = require('unlock-perplexity');
const token = getSavedToken();clearSavedSession()
Deletes the session file at ~/.perplexity_session.
const { clearSavedSession } = require('unlock-perplexity');
clearSavedSession();isAuthenticated()
Returns true if any session source is available without creating a full PerplexityApp instance.
const { isAuthenticated } = require('unlock-perplexity');
if (!isAuthenticated()) {
console.log("Please log in first.");
}Environment Variables
| Variable | Description |
|----------|-------------|
| PERPLEXITY_TOKEN | Pre-set session token; used if no other source is found |
| DEBUG_PERPLEXITY | Set to 1 to enable verbose Python debug logs |
How It Works
Your Code (JS)
│
▼
PerplexityApp.ask() ← Node.js wrapper
│
│ spawns
▼
core.py ← Python worker
│
│ curl_cffi (Chrome 120 TLS fingerprint)
▼
www.perplexity.ai ← Perplexity's socket.io API
│
└── socket.io polling (EIO=4)
├── GET /socket.io?EIO=4&transport=polling → SID
├── POST /socket.io?...&sid=... → Auth
├── POST /socket.io?...&sid=... → Send query
└── GET /socket.io?...&sid=... (loop) → Stream answerThe browser impersonation with curl_cffi is what allows this to pass Cloudflare's bot detection — it mimics the exact TLS handshake of a real Chrome 120 browser.
License
MIT
