# Buy Me a Coffee Scraper (`sashaebashu/buymeacoffee-scraper`) Actor

Read any public Buy Me a Coffee creator: every individual payment with its date and size, membership levels and prices, follower count, posts with view counts — plus alerts when new money comes in, a price moves, or a creator goes quiet.

- **URL**: https://apify.com/sashaebashu/buymeacoffee-scraper.md
- **Developed by:** [Sasha Ebashu](https://apify.com/sashaebashu) (community)
- **Categories:** Social media, Lead generation, Automation
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $15.00 / 1,000 results

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.

Learn more: https://docs.apify.com/platform/actors/running/actors-in-store#pay-per-event

## What's an Apify Actor?

Actors are web data automations that power AI and operations. They run on the Apify platform to scrape websites, process data, connect APIs, and automate workflows.
In Batch mode, an Actor accepts a well-defined JSON input, performs an action which can take anything from a few seconds to a few hours,
and optionally produces a well-defined JSON output, datasets with results, or files in key-value store.
In Standby mode, an Actor provides a web server which can be used as a website, API, or an MCP server.
Actors are written with capital "A".

## How to integrate an Actor?

If asked about integration, you help developers integrate Actors into their projects.
You adapt to their stack and deliver integrations that are safe, well-documented, and production-ready.
The best way to integrate Actors is as follows.

- **AI agents and MCP clients** — the [Apify MCP server](https://docs.apify.com/integrations/mcp.md) at `https://mcp.apify.com` (remote, streamable HTTP, OAuth on first use).
- **Agentic workflows and local Actor development** — [Agent Skills](https://apify.com/.well-known/agent-skills/index.json) with the [Apify CLI](https://docs.apify.com/cli/docs.md): `npm install -g apify-cli`, then `apify login`.
- **JavaScript/TypeScript projects** — the official [JS/TS client](https://docs.apify.com/api/client/js/docs.md): `npm install apify-client`.
- **Python projects** — the official [Python client](https://docs.apify.com/api/client/python/docs.md): `pip install apify-client`.
- **Any other language** — the [REST API](https://docs.apify.com/api/v2.md).

For usage examples, see the [API](#api) section below.

For more details, see Apify documentation as [Markdown index](https://docs.apify.com/llms.txt) and [Markdown full-text](https://docs.apify.com/llms-full.txt).

# README

## Buy Me a Coffee Scraper — Supporters, Payments & Membership Prices

Buy Me a Coffee is where a large part of the creator economy actually gets paid — a link in a
YouTube description, a button in a GitHub README, a tip jar under a newsletter. This Actor reads
any public creator page and returns **the individual payments**: who paid, how much, what they
wrote, and to the second when it happened — plus follower counts, membership levels and prices,
posts with their view counts, and alerts when any of it moves.

Public API. No key, no login, no proxy needed.

### The thing that makes this different

Most creator-economy data is a headline number: *"183 supporters"*. This Actor returns the
payments behind it — 257 of them for that same creator, going back to January 2021, each with a
date, a size and a name.

That turns a static profile into a time series. One creator in testing took **$718 in June, $502
in July, $297 in August**; another went from 14 payments in a month to 37. Neither fact is
published anywhere on the platform — both fall straight out of the feed.

| | |
|---|---|
| **Payments** | Every support: supporter, type, units, value, message, timestamp — back to the creator's first ever |
| **Monthly curve** | Payments, units and value bucketed by month, oldest first |
| **Momentum** | Last 30 days against the 30 before them |
| **Concentration** | What share of support comes from the top one, and the top five |
| **Audience** | Followers, distinct supporters, and how many of them the public feed accounts for |
| **Pricing** | Price per unit and currency, membership monthly and yearly, every level with its benefits |
| **Posts** | Title, date, views, likes, and whether the post sits behind the membership paywall |
| **Shop** | How many items they sell, how many have sold in total, and the featured items with their own sales counts |
| **Goal** | Funding target, amount raised, progress and whether it is still open |
| **Profile** | Country, occupation, verification, website, Twitter, intro video, linked socials, wishlist |

### The one number that is not an estimate

Creators can choose to publish their membership earnings on their own page. When they do, the
Actor reports it: one open-source project in testing shows **$186.90 a month from 36 subscribers**
— their figure, published by them, not a follower count multiplied by a price.

Most creators keep it private, and for those `monthlyMembershipIncome` is empty rather than
guessed. `membershipIncomeIsPublic` says which case you are looking at, so an empty field is never
mistaken for a creator earning nothing.

### Discovery: find creators, don't just read them

Buy Me a Coffee publishes its own creator index as sitemaps — **57 files of 5,000 handles** at the
time of writing. Switch on **Discover creators** and the Actor walks that index and keeps whoever
matches your filters: minimum supporters, minimum followers, country, membership on sale, or paid
within the last N days.

Filters run in cost order. Supporter and follower counts are checked on the profile, before any
history is fetched. "Paid within" is answered from the first page of the feed, so a creator who has
been silent for years costs one request instead of ten.

Measured: scanning 400 creators for those with 10+ supporters took **14 seconds and returned 22**.
Scanning 2,500 for creators with 50+ supporters paid within the last week took **4 minutes 38
and returned 11** — among them a browser project with 595 supporters and one creator with 2,366.

### What this refuses to guess

**No revenue total.** A payment's value is its units times the creator's price, and that price is
the price **today** — the API does not say what it was in 2021. So the figure is called
`oneOffValueAtCurrentPrice`, not "earnings", and memberships are left out of it entirely because
the feed never names which level was bought. You get the units, the price, the dates and the
membership count; the conclusion is yours.

**No supporter count of its own.** The profile's `public_supporters_count` is a headcount of
**people**, not payments — verified against four creators walked end to end, where it matched the
distinct payers exactly. It is reported as-is next to the payments actually counted, and the two
are never conflated.

**No window it did not see.** "Payments in the last 30 days" is only reported if the read reached
back 30 days. On a busy creator, 20 payments can span a fortnight; counting those as a monthly
total would under-report the creator and look like a slowdown that never happened. Windows the read
does not cover come back empty, and `oldestSupportRead` says exactly how far back it got.

### Monitor mode

Run it on a schedule against the creators you sponsor, compete with, or invest in.

| `changeType` | Means |
|---|---|
| **`new_supports`** | They were paid since the last run — **`newSupports` lists each payment**, with `newSupportsValueAtCurrentPrice` for the batch |
| **`price_change`** | The price per unit or a membership price moved, with the old and new figure in the creator's own currency |
| `new_posts` | They published since the last run |
| `went_quiet` | The run where they crossed your dormancy threshold — announced once, not repeated |
| `followers_up` / `followers_down` | Audience moved, with `followersDelta` |
| **`no_longer_available`** | The page is gone — closed, renamed or suspended |
| `new`, `unchanged` | First sighting / nothing moved |

**History is remembered per creator, not per list.** Adding one creator to a watchlist does not
reset the other ninety-nine — a baseline belongs to a creator, and editing your list is not an
event worth throwing it away for.

A creator who 404s but was **never** in your baseline is reported as a probable typo, not as news.

### Notes & limits

Properties of the source, measured rather than assumed:

- **The support feed serves 20 rows per request and no more** — `per_page=21` answers HTTP 422. So
  depth costs requests, and nothing can shorten that: 200 payments is 10 round trips.
- **The end of the feed is a short page followed by an empty one.** There is no total and no last
  page in the response, which means a *failed* page looks exactly like the end of somebody's
  history. A page that never succeeds therefore stops the walk and marks the result
  `supportsPartial`, rather than quietly reporting a shorter earnings record than the creator has.
- **Units are not always whole numbers.** A supporter who pays a custom amount arrives as a
  fraction: 2.5 "coffees" at $2 is a $5 payment. The message text rounds this to "bought a coffee",
  so the number is the reliable half and the sentence is not — checked across 282 payments, where
  the only two disagreements were exactly these fractional ones.
- **The unit is whatever the creator named it.** Coffee, beer, pizza, books, hot chocolate and
  "bag of apples" all appeared in a 30-creator sample. It is reported as `supportUnit`.
- **"Someone" is not a person.** It is what the platform prints when a supporter gives no name, and
  it arrives looking like an ordinary public name. Treated as one, it would top the leaderboard and
  merge every anonymous payer into a single fictional supporter, so it is flagged `isAnonymous`
  instead. Payments hidden by the supporter still show their size — only the identity is withheld.
- **The public feed can hold fewer people than the profile claims.** On two creators out of six
  walked to the end it did (172 against 183, 33 against 68); some payments are simply not listed.
  `supportersMissingFromFeed` reports that gap, and only after a complete walk — on a partial read
  the shortfall would be an artefact of your own limit.
- **A creator's post count and their listed posts are different numbers.** One profile reports 38
  posts while the API lists 9 and says so in `meta.total`; the rest are not served to anonymous
  callers. Both are published, so 9-out-of-38 reads as a fact about the paywall rather than as
  truncation.
- **Some profile fields are raw PHP `serialize()` output** leaking through the JSON API — the links
  field reads `N;` and membership perks arrive as `a:2:{i:0;s:72:"…";…}`. The strings are extracted;
  anything unrecognisable is dropped rather than echoed as escaped noise.
- **Creator links usually have no scheme** — `oldbonesphoto.com`, not `https://oldbonesphoto.com`.
  They are normalised before being classified, otherwise nearly all of them are thrown away.
- **The shop comes from the page, not the API.** There is no shop endpoint — the JSON API answers
  404 for every spelling of it. The creator page embeds the data instead, which is where the shop,
  the funding goal and the published income are read from, at the cost of one extra request per
  creator. Turn it off when scanning thousands of creators; the page is far heavier than the API.
- **The page ships only the featured shop items, never the whole catalogue.** One creator lists 7
  items and 22 sales in the totals while showing 2 on the page. Both are reported —
  `shopItemsTotal` and `shopSalesTotal` are the real figures, and `shopFeaturedItems` is a sample
  of them whenever the counts disagree.
- **No rate limiting observed.** 24 requests at 8 in parallel returned 24 × HTTP 200 without a
  single throttle; 36 creators with full payment and post lists finished in **10.4 seconds**.
- **No proxy required.** The API answered from every region tested, including one whose IP other
  parts of the site were challenging. Proxy support is there if you want it, and off by default.
- The Actor honours your **Maximum cost per run** and stops when the cap is reached.

### Input

| Field | What it does |
|---|---|
| **Creators** | Profile URLs, post URLs or bare handles — `https://buymeacoffee.com/sindresorhus`, `@sindresorhus` and `sindresorhus` all work and de-duplicate. |
| **Discover creators / Creators to scan** | Search the platform index instead of naming anyone. |
| **Minimum supporters / followers / Countries / Membership / Paid within** | Filters. They narrow a named list too, not only discovery. |
| **Read the support feed / Supports per creator** | How far back to read. This is what the earnings timeline is built from. |
| **Include the individual supports** | Adds every payment to the row rather than just the totals. |
| **Include membership levels** | Every level with monthly and yearly price and its benefits. One request per creator. |
| **Include posts / Posts per creator** | Titles, dates, views, likes and paywall status. Creators with no posts cost nothing. |
| **Include shop, funding goal and published income** | Reads the creator page for what the API does not serve. One extra request each, and a heavy one. |
| **Include wishlist** | Their published wishlist, if any. One request per creator. |
| **Treat as dormant after** | Your definition of quiet, not a hidden constant. |
| **Monitor mode / Output only changes** | The alert behaviour above. |

# Actor input Schema

## `creators` (type: `array`):

Buy Me a Coffee profile URLs or handles. Paste `https://buymeacoffee.com/sindresorhus`, a link to one of their posts, or just `sindresorhus`.

## `discoverCreators` (type: `boolean`):

Search the platform instead of naming creators yourself. Buy Me a Coffee publishes its own creator index, so this walks it and keeps whoever matches the filters below. Works alongside a named list — the named ones are read first.

## `maxCreatorsToScan` (type: `integer`):

How many creators discovery may check. Checking one costs a single request, and most will not match your filters — so scan far more than you expect to keep.

## `minSupporters` (type: `integer`):

Keep only creators with at least this many supporters. Checked on the profile, before any history is read.

## `minFollowers` (type: `integer`):

Keep only creators with at least this many followers.

## `countries` (type: `array`):

Two-letter country codes to keep, for example `US`, `GB`, `DE`. Leave empty for any country.

## `requireMembership` (type: `boolean`):

Keep only creators with a membership currently on sale.

## `activeWithinDays` (type: `integer`):

Keep only creators who took a payment this recently. Answered from the first page of the feed, so a creator who fails it costs one request rather than a full walk. 0 turns it off.

## `includeSupports` (type: `boolean`):

Reads the creator's individual payments — who paid, how many coffees, what they wrote and when. This is what makes the earnings timeline possible; without it you only get the profile's own counters, which are stale.

## `maxSupportsPerCreator` (type: `integer`):

How far back to read. The API serves 20 per request and offers no larger page, so 200 supports costs 10 requests. Set it high enough to cover the period you care about — the feed reaches back to the creator's very first payment.

## `includeSupportList` (type: `boolean`):

Adds every payment to the output — supporter, type, units, value, message and timestamp. Off by default because it makes rows large; the totals and averages are always included either way.

## `includeLevels` (type: `boolean`):

Every membership level with its monthly and yearly price and the benefits it promises. One extra request per creator.

## `includePosts` (type: `boolean`):

Reads the creator's posts — title, date, view and like counts, and whether each one is behind the membership paywall. Creators with no posts cost no extra request.

## `maxPostsPerCreator` (type: `integer`):

How many posts to read, newest first.

## `includePostList` (type: `boolean`):

Adds every post read to the output rather than just the counts and averages.

## `includeShopAndGoals` (type: `boolean`):

Reads the creator page for what the JSON API does not serve: shop items with how many were sold, the funding goal and its progress, and — for creators who choose to publish it — their actual monthly membership income and subscriber count. One extra request per creator, and a heavier one, so switch it off when scanning thousands.

## `includeWishlist` (type: `boolean`):

Reads the creator's wishlist, if they publish one. One extra request per creator.

## `dormantAfterDays` (type: `integer`):

Days since the last support before a creator counts as dormant. Drives `isDormant` and the `went_quiet` alert.

## `maxItems` (type: `integer`):

Stop after this many creators.

## `maxConcurrency` (type: `integer`):

4 is comfortable. The API took 24 requests at 8 parallel without a single throttle, so raising this is safe if you are reading many creators.

## `monitorMode` (type: `boolean`):

Compare against the last run and label what changed: new payments and what they were worth, a price rise, new posts, a creator going quiet or disappearing. The history is remembered per creator, so you can add and remove creators from the list without resetting it.

## `onlyChanges` (type: `boolean`):

With monitor mode on, skip creators where nothing moved — an empty run then means nothing needs your attention.

## `proxyConfiguration` (type: `object`):

Optional and off by default. This API answers without a proxy from every region tested; switch one on only if you get errors.

## Actor input object example

```json
{
  "creators": [
    "https://buymeacoffee.com/sindresorhus",
    "oldbonesphoto",
    "radiant"
  ],
  "discoverCreators": false,
  "maxCreatorsToScan": 1000,
  "minSupporters": 0,
  "minFollowers": 0,
  "countries": [],
  "requireMembership": false,
  "activeWithinDays": 0,
  "includeSupports": true,
  "maxSupportsPerCreator": 200,
  "includeSupportList": false,
  "includeLevels": true,
  "includePosts": true,
  "maxPostsPerCreator": 50,
  "includePostList": false,
  "includeShopAndGoals": true,
  "includeWishlist": false,
  "dormantAfterDays": 90,
  "maxItems": 100,
  "maxConcurrency": 4,
  "monitorMode": false,
  "onlyChanges": false,
  "proxyConfiguration": {
    "useApifyProxy": false
  }
}
```

# Actor output Schema

## `overview` (type: `string`):

No description

## `earnings` (type: `string`):

No description

## `alerts` (type: `string`):

No description

## `full` (type: `string`):

No description

## `money` (type: `string`):

No description

# API

You can run this Actor programmatically using our API. Below are code examples in JavaScript, Python, and CLI, as well as the OpenAPI specification and MCP server setup.

## JavaScript example

```javascript
import { ApifyClient } from 'apify-client';

// Initialize the ApifyClient with your Apify API token
// Replace the '<YOUR_API_TOKEN>' with your token
const client = new ApifyClient({
    token: '<YOUR_API_TOKEN>',
});

// Prepare Actor input
const input = {
    "creators": [
        "https://buymeacoffee.com/sindresorhus",
        "oldbonesphoto",
        "radiant"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("sashaebashu/buymeacoffee-scraper").call(input);

// Fetch and print Actor results from the run's dataset (if any)
console.log('Results from dataset');
console.log(`💾 Check your data here: https://console.apify.com/storage/datasets/${run.defaultDatasetId}`);
const { items } = await client.dataset(run.defaultDatasetId).listItems();
items.forEach((item) => {
    console.dir(item);
});

// 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/js/docs

```

## Python example

```python
from apify_client import ApifyClient

# Initialize the ApifyClient with your Apify API token
# Replace '<YOUR_API_TOKEN>' with your token.
client = ApifyClient("<YOUR_API_TOKEN>")

# Prepare the Actor input
run_input = { "creators": [
        "https://buymeacoffee.com/sindresorhus",
        "oldbonesphoto",
        "radiant",
    ] }

# Run the Actor and wait for it to finish
run = client.actor("sashaebashu/buymeacoffee-scraper").call(run_input=run_input)

# Fetch and print Actor results from the run's dataset (if there are any)
print(f"💾 Check your data here: https://console.apify.com/storage/datasets/{run.default_dataset_id}")
for item in client.dataset(run.default_dataset_id).iterate_items():
    print(item)

# 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/python/docs/quick-start

```

## CLI example

```bash
echo '{
  "creators": [
    "https://buymeacoffee.com/sindresorhus",
    "oldbonesphoto",
    "radiant"
  ]
}' |
apify call sashaebashu/buymeacoffee-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,sashaebashu/buymeacoffee-scraper"
        }
    }
}

```

The hosted server signs you in with OAuth on first connect, so no API token belongs in this config. Clients without OAuth support can send an `Authorization: Bearer <APIFY_API_TOKEN>` header instead, using a token from API & Integrations in Apify Console (https://console.apify.com/settings/integrations).

## OpenAPI specification

Download the OpenAPI definition: https://api.apify.com/v2/actors/bTeRvXAPOMgXFM3Cb/builds/oLf1xiBra8fgIqOBs/openapi.json
