# Product Hunt Scraper — Launches, Makers & Comments (`zkill3r/producthunt-scraper`) Actor

Scrape Product Hunt launches from daily/weekly/monthly/yearly leaderboards (any date or range), topics, searches or URLs. Get website, upvotes, ranks, badges, topics, pricing, media, hunter, makers and comments. $1.50/1k all-in, no login.

- **URL**: https://apify.com/zkill3r/producthunt-scraper.md
- **Developed by:** [Zee Lex](https://apify.com/zkill3r) (community)
- **Categories:** Lead generation, Marketing
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $1.25 / 1,000 launch scrapeds

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

## Product Hunt Scraper

Scrape **Product Hunt** launches from the daily, weekly, monthly or yearly leaderboard (any date or date range), from topics and searches, or from a list of URLs. Get each launch's name, tagline, description, real website, upvotes, comments, ranks, badges, topics, pricing, images, video links, the hunter, the makers with their social links, and optionally the comments. **No login needed.**

Built for **reliability**. Every launch is validated before it's saved. Cloudflare challenges are detected and retried on fresh sessions, then on residential proxies, then optionally in a real browser. The run **fails with a clear message** instead of quietly returning empty or half-finished data. A day with genuinely no launches finishes successfully with a clear "No launches found" status.

### Use cases

- **Lead generation**: reach makers of new launches in your niche, with their profile, X/Twitter and website links
- **Competitor and market research**: track what launches in your category, how it ranks and how users react
- **Investor deal-flow**: scan every day's top launches over any date range
- **Tracking top AI tools**: follow the `artificial-intelligence` topic or daily AI winners
- **Content and newsletters**: build "best launches of the week" lists with real ranks and badges

### Input

| Field | Type | Default | Notes |
|---|---|---|---|
| `mode` | string | `leaderboard` | `leaderboard`, `search` or `urls` |
| `period` | string | `daily` | Leaderboard: `daily`, `weekly`, `monthly`, `yearly` |
| `date` | YYYY-MM-DD | today (Pacific Time) | Leaderboard: single date |
| `dateFrom` / `dateTo` | YYYY-MM-DD | – | Leaderboard: every day/week/month/year in the range |
| `searchTerms` | string\[] | – | Search mode: keywords or product names |
| `topics` | string\[] | – | Search mode: topic slugs, e.g. `artificial-intelligence` |
| `startUrls` | URL list | – | URLs mode: launch, product, topic, user, search or leaderboard URLs |
| `maxItems` | integer | `100` | Total launches across all inputs |
| `includeMakers` | boolean | `true` | Open launch pages for makers, hunter and full details |
| `includeComments` | boolean | `false` | Collect comments |
| `maxCommentsPerLaunch` | integer | `20` | Used only with comments on |
| `resolveWebsiteUrls` | boolean | `true` | Follow Product Hunt's `/r/` link to the real website |
| `usePlaywright` | boolean | `false` | Browser fallback for Cloudflare and "load more" |
| `proxyConfiguration` | object | Apify Proxy (datacenter) | Escalates to residential automatically when needed and available |

#### Example: today's daily leaderboard

```json
{ "mode": "leaderboard", "period": "daily", "maxItems": 50 }
```

#### Example: every day's launches in a date range

```json
{
    "mode": "leaderboard",
    "period": "daily",
    "dateFrom": "2026-10-01",
    "dateTo": "2026-10-07",
    "maxItems": 500
}
```

#### Example: a topic

```json
{ "mode": "search", "topics": ["artificial-intelligence"], "maxItems": 20 }
```

#### Example: a search

```json
{ "mode": "search", "searchTerms": ["ai video editor"], "maxItems": 30, "usePlaywright": true }
```

#### Example: a list of URLs with comments

```json
{
    "mode": "urls",
    "startUrls": [
        { "url": "https://www.producthunt.com/posts/some-launch" },
        { "url": "https://www.producthunt.com/products/some-product" },
        { "url": "https://www.producthunt.com/leaderboard/weekly/2026/43" }
    ],
    "includeComments": true
}
```

A product URL returns all of that product's launches. A topic or search returns the latest launch of each product found.

### Output sample

A real launch (trimmed: 1 of 20 comments, 2 of 3 makers, 2 of 5 media):

```json
{
    "launchId": "1278009",
    "productId": "1040495",
    "name": "Strawberry 1.0",
    "slug": "strawberry-1-0",
    "tagline": "AI Browser that saves your team >100h/week",
    "description": "Strawberry is an AI browser that can do hours of work in minutes. Strawberry's agents, which we call \"Companions\", can research hundreds of leads in p…",
    "launchUrl": "https://www.producthunt.com/posts/strawberry-1-0",
    "productUrl": "https://www.producthunt.com/products/strawberry",
    "websiteUrl": "https://strawberrybrowser.com",
    "launchDate": "2026-10-26T07:01:00.000Z",
    "dailyRank": 1,
    "weeklyRank": 1,
    "upvotes": 334,
    "commentsCount": 64,
    "reviewsCount": 13,
    "rating": 4.85,
    "topics": [
        "Productivity",
        "Artificial Intelligence"
    ],
    "pricingType": "freemium",
    "thumbnail": "https://ph-files.imgix.net/c35c35a2-a69b-4705-ae4e-3611f14b13ff.png",
    "media": [
        {
            "type": "image",
            "url": "https://ph-files.imgix.net/231213b0-bf17-454a-9377-89bb7c954260.png",
            "videoUrl": null
        },
        {
            "type": "image",
            "url": "https://ph-files.imgix.net/c7efe950-35fe-4b5a-a1e4-6ed9600fc192.png",
            "videoUrl": null
        }
    ],
    "hunter": {
        "name": "Chris Messina",
        "username": "chrismessina",
        "profileUrl": "https://www.producthunt.com/@chrismessina"
    },
    "makers": [
        {
            "name": "Arian Hanifi",
            "username": "coffecup25",
            "profileUrl": "https://www.producthunt.com/@coffecup25",
            "headline": "cto @ strawberry",
            "twitter": null,
            "website": null
        },
        {
            "name": "Charles Maddock",
            "username": "charles_maddock",
            "profileUrl": "https://www.producthunt.com/@charles_maddock",
            "headline": "CEO @ Strawberry",
            "twitter": null,
            "website": null
        }
    ],
    "badges": [
        "Product of the Day #1"
    ],
    "dataSource": "launch_page",
    "scrapedAt": "2026-10-27T10:49:57.976Z",
    "comments": [
        {
            "author": {
                "name": "Charles Maddock",
                "username": "charles_maddock",
                "profileUrl": "https://www.producthunt.com/@charles_maddock"
            },
            "text": "Hi everyone! Charles here, and I'm really excited to share Strawberry 1.0 with you 🍓 A year ago we launched our beta here on Product Hunt. B…",
            "upvotes": 15,
            "date": "2026-10-24T19:53:54.000Z",
            "isMaker": true,
            "replies": []
        }
    ]
}
```

Field notes:

- `websiteUrl` is the product's real website (from Product Hunt's own data) with `utm_*`, `ref=producthunt` and `src=producthunt` removed. If only Product Hunt's `/r/` link is known and it can't be followed, that link is returned instead (still clickable); `RUN_SUMMARY` counts these.
- Topic and search inputs return each listed product's **latest launch**, in the order Product Hunt lists the products.
- `reviewsCount` and `rating` describe the product (all its launches). New products often have `0`.
- `dailyRank` / `weeklyRank` come from Product Hunt's data, or from the leaderboard order when the data lacks them.
- `pricingType` is `free`, `paid` or `freemium` when Product Hunt shows it, else `null`.
- `twitter` and `website` for makers are filled only when the maker has made them public.
- `comments` include replies, in page order, and appear only with `includeComments` on.
- `launchDate` falls back to the leaderboard day (date-level precision) when the exact time isn't available.
- `dataSource` is `launch_page` when the launch page was read, or `listing` when only leaderboard/topic data was used (makers off, or the launch page stayed blocked).

### Pricing

**$1.50 per 1,000 launches** (Free plan), less on paid plans: $1.40 Bronze, $1.30 Silver, $1.25 Gold and up. Plus a tiny $0.00005 per run start.

That one price covers the full record: makers, hunter, real website, media, badges, ranks and, if you turn them on, the comments. There are no extra per-maker or per-detail charges, and Apify platform usage is included, so you pay only per launch saved. Blocked or invalid launches are never saved, so they are never charged.

### Speed tip

Turn **off** `includeMakers` (and keep comments off) when you only need names, taglines, ranks, upvotes, topics and links. The Actor then reads only leaderboard or topic pages instead of opening every launch, so runs finish several times faster.

Plain HTTP mode runs fine at 1024 MB. Turn on `usePlaywright` only when you need it, and give the run 2048 MB or more.

### Reliability and run status

- Launches without a launch URL, name or launch date are dropped and counted, never saved. Launches are deduplicated across all inputs.
- Cloudflare challenges ("Just a moment…", `cf-chl`, `cf-mitigated`), HTTP 403/429/503 and pages with no launch data are treated as blocks. Each request is retried up to 4 times on fresh sessions. From the 3rd attempt it switches to residential proxies (if your account has them), and with `usePlaywright` it finally gets a real-browser attempt.
- If a launch page stays blocked but the leaderboard already had its data, the launch is still saved from the listing (`dataSource: "listing"`) and doesn't count as lost.
- The run **fails** with a clear message when:
  - nothing was saved although results were expected,
  - 20 blocks happen in a row, or
  - at least 25% of requests were truly lost.
- `RUN_SUMMARY` (linked from the run's Output tab) shows saved and dropped launches, missing-field percentages, block reasons, residential escalations and browser fallbacks.

### Limitations

- Product Hunt sits behind Cloudflare. Most pages load over plain HTTP, but some sessions get challenged. Residential proxies and the browser fallback raise the success rate, but no setting guarantees it.
- Topic and search results are paged automatically (`?page=2`, `3`, …) until `maxItems` is reached.
- Comments are the top threads by votes with their replies, up to `maxCommentsPerLaunch`.
- The browser fallback (`usePlaywright`) reads launch pages instead of Product Hunt's API, so `reviewsCount` can be missing on launches it had to rescue.
- The Actor reads Product Hunt's own page data, which can change. Rising missing-field percentages in `RUN_SUMMARY` are the early warning.
- Only publicly visible data is collected. Product Hunt also offers an official API for approved uses. You're responsible for how you use the data, including contacting makers in line with anti-spam and privacy laws.

### Development

```bash
npm install
npm test                                   # offline parser tests
apify run                                  # live run
```

Offline end-to-end check against a local Product Hunt stand-in (includes a simulated Cloudflare JS challenge):

```bash
npm run build
npm run mock-server &                      # http://127.0.0.1:4555
PH_BASE_URL=http://127.0.0.1:4555 APIFY_CHROME_EXECUTABLE_PATH=/path/to/chrome node dist/main.js
```

# Actor input Schema

## `mode` (type: `string`):

What to scrape: leaderboard launches for a date or date range, search terms and topics, or a list of Product Hunt URLs.

## `period` (type: `string`):

Leaderboard mode: daily, weekly, monthly or yearly leaderboard.

## `date` (type: `string`):

Leaderboard mode: a single date (YYYY-MM-DD, Pacific Time like Product Hunt). Leave empty, with no range, for today's leaderboard. For weekly/monthly/yearly, the period containing this date is used.

## `dateFrom` (type: `string`):

Leaderboard mode: start of a date range (YYYY-MM-DD). Every day (or week/month/year) in the range is scraped. Overrides Date.

## `dateTo` (type: `string`):

Leaderboard mode: end of the date range (YYYY-MM-DD), inclusive. Defaults to Date from.

## `searchTerms` (type: `array`):

Search mode: product names or keywords to search on Product Hunt, e.g. "ai video editor".

## `topics` (type: `array`):

Search mode: topic slugs from producthunt.com/topics/..., e.g. "artificial-intelligence".

## `startUrls` (type: `array`):

URLs mode: Product Hunt launch (/posts/...), product (/products/...), topic, maker or user (/@...), search or leaderboard URLs.

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

Maximum number of launches to save across all inputs.

## `includeMakers` (type: `boolean`):

Open each launch page to collect makers and the hunter with profile and social links, plus full launch details. Turn off (with comments off) for a faster, cheaper run using listing data only.

## `includeComments` (type: `boolean`):

Collect comments from each launch page. Opens launch pages even if makers are off.

## `maxCommentsPerLaunch` (type: `integer`):

Only used when Include comments is on. Plain HTTP mode returns the comments embedded in the page (usually the first 10-20); enable the browser fallback for more.

## `resolveWebsiteUrls` (type: `boolean`):

Follow Product Hunt's /r/ redirect to get each product's real website, with tracking parameters removed. One small extra request per launch.

## `usePlaywright` (type: `boolean`):

Retry pages that plain HTTP can't get through (Cloudflare) in a real browser, and use the browser to load more results on topic/search pages. Slower and needs more memory (use 2048 MB+).

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

Datacenter proxies are tried first. Requests that keep hitting Cloudflare challenges automatically switch to RESIDENTIAL proxies when your account has access.

## Actor input object example

```json
{
  "mode": "leaderboard",
  "period": "daily",
  "maxItems": 100,
  "includeMakers": true,
  "includeComments": false,
  "maxCommentsPerLaunch": 20,
  "resolveWebsiteUrls": true,
  "usePlaywright": false,
  "proxyConfiguration": {
    "useApifyProxy": true
  }
}
```

# Actor output Schema

## `launches` (type: `string`):

One item per Product Hunt launch.

## `runSummary` (type: `string`):

Saved and dropped counts, missing-field percentages, block reasons and fallbacks used.

# 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 = {
    "proxyConfiguration": {
        "useApifyProxy": true
    }
};

// Run the Actor and wait for it to finish
const run = await client.actor("zkill3r/producthunt-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 = { "proxyConfiguration": { "useApifyProxy": True } }

# Run the Actor and wait for it to finish
run = client.actor("zkill3r/producthunt-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 '{
  "proxyConfiguration": {
    "useApifyProxy": true
  }
}' |
apify call zkill3r/producthunt-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,zkill3r/producthunt-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/hZJ8qWlIfyHEiprbh/builds/s5EfbWdUQqNbsfyy5/openapi.json
