# Gumroad Scraper — Products, Sales, Sellers & Whop (`oswaldocarabano/gumroad-products-sellers-scraper`) Actor

Scrape Gumroad products with price in USD, ratings, public sales and revenue estimate, sellers with their whole catalog, reviews, and category snapshots with an opportunity score to find product ideas. Also Whop product pages by link. No login. Errors are never charged.

- **URL**: https://apify.com/oswaldocarabano/gumroad-products-sellers-scraper.md
- **Developed by:** [Oswaldo Carabano](https://apify.com/oswaldocarabano) (community)
- **Categories:** E-commerce, Business, Lead generation
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $1.00 / 1,000 products

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.
Since this Actor supports Apify Store discounts, the price gets lower the higher subscription plan you have.

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

## What's an Apify Actor?

An Actor is a serverless cloud program that runs on the Apify platform. It has two run modes.
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.

Apify vocabulary and the platform model are defined once, in the agent quickstart at https://apify.com/agents.md.

## 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.

Do not guess an integration path. Every one of them is in the agent quickstart at https://apify.com/agents.md: the Apify MCP server, Agent Skills with the Apify CLI, the JavaScript and Python clients, the REST API, and the account-free path for an agent with no human to sign in. It also carries the rule on stating cost before the first paid run.

For examples already wired to this Actor's own input schema, see the [API](#api) section below.

Each client library has reference documentation the quickstart does not restate: [JavaScript/TypeScript](https://docs.apify.com/api/client/js/docs.md) (`npm install apify-client`) and [Python](https://docs.apify.com/api/client/python/docs.md) (`pip install apify-client`).

# README

## Gumroad Scraper — Products, Sales, Sellers & Whop

Extract **Gumroad** and **Whop** marketplace data to find profitable digital-product ideas with real numbers: what sells, at what price, how buyers rate it, which sellers dominate, and where the demand is poorly served. Products with **price in USD**, ratings and **star histogram**, the **public sales count** (and a clearly-marked revenue estimate) when the seller shows it, full description, variants, refund policy and seller reputation; **sellers** with their whole storefront summarized; **reviews**; and **category snapshots** with a published **opportunityScore**.

No login, no account, no API key. Error rows, empty results and duplicates within a run are never charged.

### What you get

| Output type | One row per | Highlights |
|---|---|---|
| **products** (default) | Gumroad or Whop product | price in USD + original currency, ratings + 1–5★ histogram, public sales count, revenue estimate, description, variants and tiers, subscription/PWYW/free flags, refund policy, bundle content, seller reputation; Whop: plan, renewal price, trial, company members, marketplace rank |
| **sellers** | Gumroad seller | reputation, bio, X handle, every storefront product read (count, median/min/max price, product types, free/PWYW/subscription shares), top products, public sales summed over its most-rated products, last post date |
| **reviews** | written review | stars, text, date, seller reply; anonymous reviewers stay anonymous |
| **category-snapshots** | category, search term or tag | competition size, median rating, share below 4★, prices (p25/median/p75), free and PWYW shares, seller concentration, top tags and file types, top products, **opportunityScore** |

#### Field coverage (measured, not promised)

Measured on 17 Oct 2026 over **every product of one whole Gumroad category** (n = 6,473, `business-and-money/marketing-and-sales`, not just the popular ones), and **420 Whop product pages**. In brackets, a 366-page sample of the most popular products across the 18 top-level categories, to show how much popularity changes the numbers:

- Always (100%): name, URL, product type, price in original currency, ratings count, seller, verified flag. Price in USD 99.9%.
- Description 99% · cover images 98% · attributes 66% (48%) · summary 61% (51%) · rating and star histogram 51% · seller reputation 45% (76%) · seller X handle 37% (23%) · variants 16% (21%) · refund policy 12% (23%) · subscriptions 1.9% (6.6%).
- **Public sales count 20.4%** (19.1%): sellers choose to show it. **Revenue estimate 9.5%**: half of the products that show sales are "$0+" pay-what-you-want, which get no estimate.
- Pay-what-you-want 41% of products, mostly "$0+": only 1.4% are free without the pay-what-you-want option.
- Whop: price and plan 100%, company members 100%, rating and review count 100% (73% with at least one review, with the company's star histogram), description 79%.
- Product rows with the product page average **48.6 filled fields** (p10 45, p90 53) in that category. Over 50 varied runs on the platform (n = 2,486 Gumroad products, some with search cards only) the average is 41.0, and 47.0 for Whop products (n = 112). Gumroad does not publish product launch or update dates, so those fields are null.
- Tiered memberships show the cheapest tier at the default billing period (the product page itself says 0); every tier and period is in `variants`. Prices in JPY have no decimals.

### The opportunityScore (how ideas are ranked)

Every category snapshot carries `opportunityScore` (0–100) with its four components, computed on the sample of the run with a fixed, published formula (no AI, deterministic: the same sample always gives the same score):

```
score = 100 × (0.40 × demand + 0.25 × dissatisfaction + 0.20 × staleness + 0.15 × openness)
demand          = min(1, log10(1 + total demand) / 6)      total demand = Σ public sales, or Σ ratings when sales are hidden (Whop: Σ company members)
dissatisfaction = share of rated products below 4 stars
staleness       = share of products not updated in 2+ years (not measurable here: Gumroad and Whop publish no update dates, so staleness is null, stalenessMeasured is false and the score is divided by 0.80, the sum of the other three weights)
openness        = 1 / (1 + N / 50)                         N = real size of the category (populationCount: the Gumroad search total); N = sample size (opennessBasis: sample) on Whop, whose category count stops at 100, and when your filters narrow the sample
```

Formula version v1.3 (21 Oct 2026): openness uses the real number of competing products, so a small niche scores more open than a crowded category even with the same sample size; `medianDemand` is the median over the products that have a demand signal (`demandKnownCount`); and when staleness cannot be measured its weight is spread over the other three, so Gumroad and Whop categories can now reach 100 (up to v1.2 they stopped at 80).

`demandLogCap` is 6: a category whose sampled products add up to a million ratings or sales gets the full demand component. Measured on 17 Oct 2026, the 500 most-reviewed products of the biggest Gumroad categories add up to 10^4.4–10^5.4 ratings; small subcategories 10^2.3–10^3. Keep `snapshotSampleSize` equal across runs to compare categories. `competitorsInSource` and `populationCount` show the real size of the competition next to the score.

### Pricing (pay per event)

| Event | Price |
|---|---|
| Product (primary) | **$0.001** ($1.00 per 1,000) |
| Seller | $0.002 |
| Review | $0.0005 |
| Category snapshot | $0.003 |
| Actor start | $0.00001 |

Error rows, empty results and duplicates inside a run are never charged. Rows reused from the shared cache cost the same and carry `cachedAt`.

### How it compares (declared by each actor on 17 Oct 2026)

| | This actor | memo23 | muhammetakkurtt | crawloop | scrapewise |
|---|---|---|---|---|---|
| Price per product | **$0.001** | $0.005 | $0.01 → $0.002 by tier | $0.0045 | $0.004 |
| Start fee | $0.00001 | $0.005 | $0.01 | $0.01 | — |
| Output fields declared | 171 | not declared | not declared | 48 | 36 |
| Seller rows with whole catalog | yes | seller record | no | no | no |
| Reviews | yes | yes | no (separate actor) | no | no |
| Category snapshots + opportunity score | **yes** | no | no | no | no |
| Public sales + revenue estimate | yes (marked as estimate) | no | no | sales count | no |
| Whop in the same actor | **yes** | no | no | no | no |
| Error rows charged | never | — | — | — | — |

### Input examples

- Products for a search: `{"queries": ["notion template"], "maxItems": 100}`
- Best-sellers with public sales in a category: `{"taxonomies": ["business-and-money/marketing-and-sales"], "onlyWithPublicSales": true, "sortBy": "most_reviewed"}`
- Idea finder over every top category: `{"outputType": "category-snapshots"}`
- A seller's whole catalog: `{"sellerUrls": ["https://seller.gumroad.com"], "maxItems": 500}`
- Complaints to fix: `{"outputType": "reviews", "productUrls": ["https://seller.gumroad.com/l/product"], "reviewRatings": [1, 2]}`
- Whop products of a company: `{"whopUrls": ["https://whop.com/company/"]}`

Default input `{}`: 20 products in 7–16 seconds (measured on 17 Oct 2026, on Apify, with and without the shared cache).

### Good to know

- **10,000 results per search.** Gumroad returns at most the first 10,000 results of any search (measured), and only 5,000 in some categories (measured in `design/fonts`, whose price ranges add up to more). Split big searches by category, tag or price; the run status says when the limit was reached.
- **Tags** are joined with OR by Gumroad: `["notion", "procreate"]` returns products with either tag.
- **Filters.** Price and rating are sent to Gumroad and checked again on every row (Gumroad's own price filter returns extra products priced in other currencies). Product type, subscription, pay-what-you-want, free, verified seller and ratings-count filters are applied by the actor before opening product pages, so filtered products cost nothing. "Free products only" means price 0 without pay-what-you-want; use Max price 0 to include the "$0+" products. Pasted product and seller links are always returned, and when you paste links the search terms and categories are not used (the run log says so).
- **Public sales** exist only when the seller shows them. Sales filters need each product page; the run checks at most 15 product pages per requested row (at least 150) and says so in the status. With seller rows, the same filters keep sellers whose most-rated products (`sellerSalesCheckLimit`) show sales.
- **Speed.** Gumroad allows about 60 product pages per connection per minute; the actor paces each connection and spreads the work.
- **Freshness.** Rows are read live unless a page fetched in the last `maxCacheAgeHours` (default 6) is available in the shared cache; those rows carry `cachedAt` (22% of the rows in our 50 test runs). Set it to 0 to always read live.
- **Whop** rows come from Whop product and company links. Since 21 Oct 2026 Whop no longer serves its category pages (they redirect to its home page), so Whop categories and Whop category snapshots return an error row that is not charged, without retries; before that, a category page listed only its 24 most popular companies. Their products are read from the public product pages. Whop does not show sales counts.
- **Privacy.** Only public marketplace data. Email addresses and phone numbers are removed from every text field, including names; reviewer avatars are not collected; Whop owner accounts are never included, only the company.

### FAQ

**Is the revenue real?** `estimatedRevenueUsd` is an estimate (public sales count × current list price) and is labeled as such in every row. It ignores discounts, refunds, variants and past prices, and it is left empty for pay-what-you-want products and subscriptions, so expect it on about 1 product in 10.

**Why is a field empty?** The seller did not publish it (for example the sales count), or `includeDetails` is off. Keys are always present, with `null` when there is no value.

**Can I run it on a schedule?** Yes. Combine `maxCacheAgeHours: 0` with Apify schedules to track prices, ratings and sales over time.

This actor is not affiliated with, endorsed by or sponsored by Gumroad or Whop. It reads only public pages.

# Actor input Schema

## `outputType` (type: `string`):

One row type per run. <b>products</b>: full product rows (price in USD, ratings and star histogram, public sales count and revenue estimate when the seller shows sales, description, variants, refund policy, seller reputation) from search, categories, tags, product links or seller storefronts. <b>sellers</b>: one row per seller with its whole catalog summarized (prices, product types, ratings, public sales of its top products). <b>reviews</b>: written reviews of the products. <b>category-snapshots</b>: one row per category, search term or tag with market metrics and a published opportunityScore — the quickest way to find gaps worth building for.

## `source` (type: `string`):

<b>gumroad</b> (default), <b>whop</b> (Whop marketplace products: price and plan, members, ratings, ranking) or <b>all</b> (half of Max rows from each). Pasting only Whop links switches to Whop automatically. Whop rows come from Whop links (category browsing is unavailable since 21 Oct 2026).

## `queries` (type: `array`):

Gumroad search terms (e.g. "notion template", "lightroom presets"). Plain words only; links or HTML are rejected. Each search reaches at most 10,000 results (a Gumroad limit), so split huge searches by category, tag or price. Leave every list empty to browse all of Gumroad.

## `taxonomies` (type: `array`):

Gumroad categories and subcategories (361). Combined with search terms when both are given.

## `tags` (type: `array`):

Only products with ANY of these Gumroad tags (e.g. notion, procreate): Gumroad joins several tags with OR. In category snapshots without categories or search terms, one snapshot per tag.

## `fileTypes` (type: `array`):

Only products containing these file types (e.g. pdf, zip, mp4).

## `productUrls` (type: `array`):

Gumroad product pages, e.g. https://seller.gumroad.com/l/product or https://gum.co/abc. Pasted products are always returned (filters do not apply to them). Custom seller domains are not supported; each wrong entry gets one error row that is not charged.

## `sellerUrls` (type: `array`):

Gumroad storefronts, e.g. https://seller.gumroad.com. With "Products" you get every product of these sellers; with "Sellers", one summary row per seller.

## `whopCategories` (type: `array`):

Whop marketplace categories (781). Since 21 Oct 2026 Whop no longer serves its category pages (they redirect to the Whop home page): each category then returns one error row that is not charged. Use Whop links instead.

## `whopUrls` (type: `array`):

Whop product pages (https://whop.com/company/product/) or company pages (https://whop.com/company/ = all its products).

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

Rows delivered (and charged) at most. Duplicates and error rows are never charged. When you paste product links and leave this empty, every one of them is delivered.

## `sortBy` (type: `string`):

Gumroad search order. "Hot and new" also narrows the results to recent products (596 instead of 23,641 in Business & Money, measured). Price sorts use each seller's own currency, as Gumroad does.

## `minPrice` (type: `number`):

Price in USD as Gumroad converts it. Sent to Gumroad and checked again on every row (Gumroad's own price filter returns extra products in other currencies).

## `maxPrice` (type: `number`):

Price in USD. Checked on every row.

## `minRating` (type: `number`):

Average rating. Checked on every row.

## `minRatingsCount` (type: `integer`):

Only products with at least this many ratings (a proxy for real buyers).

## `maxRatingsCount` (type: `integer`):

Only products with at most this many ratings (find young or underserved niches).

## `productTypes` (type: `array`):

Only these Gumroad product types (Gumroad ignores this filter in search, so the actor applies it on each card before reading the product page).

## `subscription` (type: `string`):

Keep, only, or exclude recurring products (memberships, subscriptions).

## `payWhatYouWant` (type: `string`):

Keep, only, or exclude pay-what-you-want products.

## `freeOnly` (type: `boolean`):

Only products with price 0 that are not pay-what-you-want. Most free Gumroad products are "$0+" pay-what-you-want (117 of 149 measured) and are left out; for those use Max price 0 instead.

## `verifiedSellersOnly` (type: `boolean`):

Only products from sellers verified by the marketplace.

## `onlyWithPublicSales` (type: `boolean`):

Only products whose seller shows the number of sales (19.1% of Gumroad products, 366 measured). Needs each product page; the run checks at most 15 product pages per requested row (at least 150) and says so in the status when it stops early. Whop never shows sales. With outputType sellers: only sellers with public sales among their most-rated products (sellerSalesCheckLimit).

## `minSales` (type: `integer`):

Only products showing at least this many sales (implies the sales count is public). With outputType sellers: public sales summed over the checked products.

## `includeDetails` (type: `boolean`):

On (default): description, star histogram, public sales count, variants, refund policy, seller reputation and more (about 60 filled fields per row instead of 30). Off: search cards only, faster and lighter.

## `maxReviewsPerProduct` (type: `integer`):

For outputType reviews (10 reviews per page on Gumroad).

## `reviewRatings` (type: `array`):

For outputType reviews, e.g. \[1, 2] to read complaints. Gumroad has no such filter, so the actor applies it.

## `sellerSalesCheckLimit` (type: `integer`):

For outputType sellers: how many of the seller's most-rated products are opened to add up public sales. 0 = skip.

## `snapshotSampleSize` (type: `integer`):

For category snapshots: products sampled per category (most reviewed first). The opportunityScore is comparable between categories when this is the same.

## `snapshotWithSales` (type: `boolean`):

For category snapshots: read every sampled product page to add public sales and the revenue estimate (one more request per product).

## `maxCacheAgeHours` (type: `integer`):

When a shared cache is available, a product, seller or Whop page fetched by any run in the last N hours is reused. Reused rows carry cachedAt and cost the same. 0 = always live.

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

Connections in use at once. Gumroad allows about 60 product pages per connection per minute; the actor paces each connection and spreads work across them.

## Actor input object example

```json
{
  "outputType": "products",
  "source": "gumroad",
  "queries": [],
  "taxonomies": [],
  "tags": [],
  "fileTypes": [],
  "productUrls": [],
  "sellerUrls": [],
  "whopCategories": [],
  "whopUrls": [],
  "maxItems": 20,
  "sortBy": "default",
  "productTypes": [],
  "subscription": "any",
  "payWhatYouWant": "any",
  "freeOnly": false,
  "verifiedSellersOnly": false,
  "onlyWithPublicSales": false,
  "includeDetails": true,
  "maxReviewsPerProduct": 20,
  "reviewRatings": [],
  "sellerSalesCheckLimit": 10,
  "snapshotSampleSize": 100,
  "snapshotWithSales": false,
  "maxCacheAgeHours": 6,
  "maxConcurrency": 8
}
```

# Actor output Schema

## `results` (type: `string`):

The rows of this run: products, sellers, reviews or category snapshots, depending on the outputType you chose.

## `errors` (type: `string`):

Every error of the run with its reason and what to do. Always present, empty when nothing failed.

## `summary` (type: `string`):

Counts of delivered, charged, duplicate, filtered and error rows for this run.

# 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 = {
    "maxItems": 20
};

// Run the Actor and wait for it to finish
const run = await client.actor("oswaldocarabano/gumroad-products-sellers-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 = { "maxItems": 20 }

# Run the Actor and wait for it to finish
run = client.actor("oswaldocarabano/gumroad-products-sellers-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 '{
  "maxItems": 20
}' |
apify call oswaldocarabano/gumroad-products-sellers-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,oswaldocarabano/gumroad-products-sellers-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/beJC4N1IWmIaXldhl/builds/rZKokmXzL9DhBFMMN/openapi.json
