@gonzih/of-scraper
v1.0.0
Published
OnlyFans scraper that feeds messages, profiles, and financials into Redis Streams
Downloads
44
Readme
@gonzih/of-scraper
A Node.js + TypeScript service that maintains a live Puppeteer browser session logged into OnlyFans, scrapes incoming messages, and feeds them into Redis Streams.
Features
- Persistent browser sessions via
session.json(cookies + localStorage) - Polls
/my/chatsevery 30s for new messages - For each new message, scrapes:
- Sender profile (displayName, bio, profilePic, subscription status)
- Financial data (tips, purchases, lifetime value)
- All data published to Redis Streams
- Duplicate prevention via Redis SET
of:seen_messages - Stealth mode via
puppeteer-extra-plugin-stealth
Prerequisites
- Node.js 18+
- Redis 6+ (running locally or via
REDIS_URL)
Setup
npx @gonzih/of-scraperOr install globally:
npm install -g @gonzih/of-scraper
of-scraperInitial Login
On first run (or when the session has expired), the service opens a browser window and waits for you to log in manually:
- Set
HEADLESS=falseto see the browser - Log in to OnlyFans in the browser window
- The service detects the successful login, saves
session.json, and starts polling
Subsequent runs will restore the saved session automatically.
Environment Variables
| Variable | Default | Description |
|----------|---------|-------------|
| REDIS_URL | redis://localhost:6379 | Redis connection URL |
| POLL_INTERVAL_MS | 30000 | Polling interval in milliseconds |
| SESSION_FILE | ./session.json | Path to session persistence file |
| HEADLESS | true | Run browser headlessly (false for initial login) |
Redis Stream Schemas
of:messages
| Field | Type | Description |
|-------|------|-------------|
| messageId | string | Unique message identifier |
| fromUsername | string | Sender's OnlyFans username |
| text | string | Message text content |
| timestamp | string | ISO 8601 timestamp |
| threadId | string | Chat thread ID |
of:profiles
| Field | Type | Description |
|-------|------|-------------|
| username | string | OnlyFans username |
| displayName | string | Display name |
| isSubscribed | string | "true" or "false" |
| profilePic | string | URL of profile picture |
| bio | string | Profile bio text |
| fetchedAt | string | ISO 8601 fetch timestamp |
of:financials
| Field | Type | Description |
|-------|------|-------------|
| username | string | OnlyFans username |
| totalTips | string | Total tips received from this fan |
| totalPurchases | string | Total PPV/content purchases |
| subscriptionStatus | string | Current subscription status |
| lastPaymentDate | string | Date of last payment |
| lifetimeValue | string | Total lifetime spend |
| updatedAt | string | ISO 8601 update timestamp |
Consuming Streams
# Read all messages from the beginning
redis-cli XREAD COUNT 10 STREAMS of:messages 0-0
# Read new messages since last read (consumer group pattern)
redis-cli XGROUP CREATE of:messages myapp $ MKSTREAM
redis-cli XREADGROUP GROUP myapp consumer1 COUNT 10 STREAMS of:messages >Error Handling
If the service cannot verify the login state, it saves a screenshot to /tmp/of_login_required.png for debugging. Delete session.json and restart with HEADLESS=false to re-authenticate.
Architecture
src/
browser.ts — Puppeteer session management (launch, save, restore)
messages.ts — Scrape chat list, extract new messages
profiles.ts — Scrape profile details for a username
financials.ts — Scrape transaction/tip history for a username
redis.ts — Redis client + XADD stream helpers
index.ts — Main loop + orchestration