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

patreon-scraper-api

v0.0.1

Published

Patreon scraper API client: public creator pages, tier prices, about text and structured profile data via ScrapingBee.

Readme

patreon-scraper-api

Public Patreon creator data for Node, organised by what you are trying to find out.

npm install patreon-scraper-api

Node 16 or newer. One dependency, axios.

const { PatreonScraper } = require('patreon-scraper-api');
const bee = new PatreonScraper(process.env.SCRAPINGBEE_API_KEY);

Key with 1,000 free credits: scrapingbee.com. Auth is a header, handled for you.

Run against patreon.com/kurzgesagt on 2026-09-10. Values below are recorded output.


First, what you cannot get

Worth settling before you build. Patron identities, member lists, individual pledge amounts, patron only posts and attachments all sit behind a login. Scraping under login credentials is prohibited by ScrapingBee's terms of service, so no option on this client reaches them and none of the examples pretend to.

Everything below reads what Patreon shows an anonymous visitor.

"I need a creator's name and what they make"

Cheapest and sturdiest. 5 credits.

const c = await bee.creator('kurzgesagt');

c.creator;           // 'Kurzgesagt – In a Nutshell'
c.campaign_tagline;  // 'Creating Science Animation Videos'
c.og_desc;           // the short description Patreon shows to search engines

campaign_tagline is computed, not scraped. Patreon glues the creator name and the tagline together in the page title with an em dash, and a creator name can itself contain an en dash, so the split is safe. The client does it.

This route reads OpenGraph and title tags, which exist so share links render. They are the last thing on a Patreon page that will move.

"I need the whole about text, for search or embeddings"

5 credits, same page, richer output.

const p = await bee.profile('kurzgesagt');

p.name;        // 'Kurzgesagt – In a Nutshell'
p.about;       // 4,476 characters on the live page
p.image;       // full size avatar
p.thumbnail;   // 360px version

creator() gives you roughly 160 characters of description. profile() gives 4,476, because it reads the ProfilePage object out of the page's structured data rather than the truncated meta tag.

One thing to know if you build this yourself: the extraction rule engine cannot read script tag contents. Selecting script[type="application/ld+json"] returns null, tested directly. So this fetches the page and parses the block. It also matches on @type rather than block index, because the live page carried six blocks and one of them describes Patreon the company rather than the creator.

"I need every tier and what it costs"

5 credits.

const ladder = await bee.priceLadder('kurzgesagt');
[{ title: 'Free',             price: 0,    currency: 'USD', free: true,  posts: 8  },
 { title: 'Trainee Producer', price: 3.14, currency: 'USD', free: false, posts: 1  },
 { title: 'Producer',         price: 15,   currency: 'USD', free: false, posts: 62 },
 { title: 'Senior Producer',  price: 42,   currency: 'USD', free: false, posts: 58 }]

For the raw objects, with every field Patreon ships:

const t = await bee.tiers('kurzgesagt');
t.matched;   // true
t.count;     // 4
t.tiers[1];  // { title, amount_cents, currency, description, url, image_url,
             //   is_free_tier, post_count, published, requires_shipping,
             //   declined_patron_count, patron_amount_cents, patron_currency,
             //   discord_role_ids, remaining, user_limit }

Do not read declined_patron_count as a patron count. It counts declined payments. Across those four tiers it reads 2, 31, 14 and 0, which is not a membership figure for a channel that size. Patreon publishes no per tier patron count on the public page, and this client keeps the field under its real name instead of dressing it up.

Trust amount_cents with currency. patron_amount_cents and patron_currency are also present, reading 800 and DKK on the free tier, which is not the tier price, so they come back untouched and uninterpreted.

remaining and user_limit were both null here. They hold real numbers on creators who cap a tier.

This route parses Patreon's own bootstrap payload, which is a private format with no stability guarantee. When it stops matching you get { tiers: [], matched: false, fallback }, where fallback is the creator() result. Check matched rather than treating an empty array as a creator with no tiers.

"I only need the entry price and I do not want a parser"

30 credits. Premium proxy plus JavaScript at 25, plus 5 for the AI query.

const e = await bee.entryPrice('kurzgesagt');
e.membership_tiers;   // ['Access exclusive benefits starting at $3.14/month']
e.creator_name;       // correct
e.about;              // complete

membership_tiers comes back as one teaser string, not an array of tiers. The tier cards are mounted by a component that has not rendered when the page is captured, so the model reported what was actually visible. That is the honest output.

Note the $3.14 matches amount_cents: 314 from tiers(), so both routes agree on the entry price by two independent paths.

If you want just that number without the AI call:

const entry = await bee.entryTier('kurzgesagt');
entry.title;         // 'Trainee Producer'
entry.amount_cents;  // 314

entryTier() skips the free tier, since a price of zero is not an entry price. It costs 5 credits, not 30.

"I need to know what this is costing"

await bee.creator('kurzgesagt');
bee.lastCost;   // 5

const acct = await bee.usage();   // free

| Configuration | Credits | |---|---| | Auto mode on a creator page | 5 | | Premium proxy plus JavaScript | 25 | | The same plus an AI query | 30 | | Validation error | 0 |

Auto mode walks the proxy ladder cheapest first and bills only the rung that worked, and nothing at all when every rung fails. On Patreon that landed on the JavaScript rung. It cannot be combined with render_js, premium_proxy or stealth_proxy, and sending both returns HTTP 400 with nothing billed, which is easy to miss if you are not checking status codes.

At 5 credits a creator, 250,000 credits is 50,000 checks. Plan tiers.

Which route for which field

| Field | Route | Credits | |---|---|---| | Name, tagline | creator | 5 | | Full about copy, avatar | profile | 5 | | Every tier, price, post count | tiers / priceLadder | 5 | | Cheapest paid tier | entryTier | 5 | | Entry price teaser, no parser | entryPrice | 30 |

creator() and profile() read the same page, so if you want both, fetch once and run both parsers locally for one charge.

Elsewhere

Other creator platform pages: Substack scraper API, Twitch API, Snapchat scraper API, TikTok follower API, TikTok search API, YouTube shorts API, YouTube comment scraper API, YouTube transcript scraper API.

Features: AI web scraping, data extraction, markdown scraper, screenshots.

Route by route walkthrough with the raw payload shapes: github.com/ScrapingBee/patreon-api.

License

MIT