npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@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/chats every 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-scraper

Or install globally:

npm install -g @gonzih/of-scraper
of-scraper

Initial Login

On first run (or when the session has expired), the service opens a browser window and waits for you to log in manually:

  1. Set HEADLESS=false to see the browser
  2. Log in to OnlyFans in the browser window
  3. 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