# Product Hunt Scraper - Daily Leaderboard, Pay Per Result (`automia-admin/product-hunt-leaderboard-scraper`) Actor

Scrape the Product Hunt daily leaderboard for any date: launch name, tagline, daily, weekly and monthly rank, comment count, topics, thumbnail and launch page. Backfill any date range. No API token needed. No personal data: voters, makers and commenters are never collected.

- **URL**: https://apify.com/automia-admin/product-hunt-leaderboard-scraper.md
- **Developed by:** [Andrés Santiso](https://apify.com/automia-admin) (community)
- **Categories:** Social media, AI, News
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $6.00 / 1,000 launches

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

## Product Hunt Scraper - Daily Leaderboard Ranking by Date

Scrapes the **Product Hunt daily leaderboard** for any date or date range and returns one
structured record per ranked launch: name, tagline, daily / weekly / monthly rank, comment
count, topics, thumbnail and the Product Hunt page.

No API token. No headless browser. Runs finish in seconds.

### What you get

One dataset item per ranked launch:

| Field | What it is |
|---|---|
| `date` | The leaderboard day, `YYYY-MM-DD` |
| `dailyRank` | Position on that day's leaderboard (1 = first) |
| `weeklyRank`, `monthlyRank` | Position in the week and month rankings, when Product Hunt has computed them |
| `name`, `tagline` | The launch name and its one-line pitch |
| `slug`, `productHuntUrl` | Product Hunt identifier and page |
| `commentsCount` | Comments on the launch |
| `launchDayScore`, `latestScore` | Product Hunt's own scoring fields, when present |
| `topics` | Topic names, e.g. `["Artificial Intelligence", "Developer Tools"]` |
| `featuredAt`, `createdAt` | Timestamps as Product Hunt reports them |
| `productState` | Launch state, as reported |
| `thumbnailUrl` | Thumbnail, built from the launch's image UUID on Product Hunt's file CDN |
| `postId` | Numeric launch id |
| `scrapedAt` | When this record was collected (UTC) |

### What it does not collect - on purpose

**No personal data.** The page payload carries voters, makers and comment authors. This
Actor never maps any of them. A launch is a product, not a person. Several scrapers in this
category sell email enrichment and owner leads; this one does not, and that is a deliberate
choice, not an omission.

Three honest limits, so the output never surprises you:

- **Vote counts are not returned.** Product Hunt hides `votesCount` in the leaderboard
  payload (it comes back `null`), so this Actor does not promise it. Use `commentsCount`,
  `launchDayScore` and the ranks instead.
- **A day returns the launches Product Hunt ranked on its daily leaderboard**, typically
  between 10 and 17. That is the leaderboard, not every submission of that day.
- **Today is never scraped.** Its leaderboard is still filling up and would look truncated.
  "Recent days" walks back from yesterday.

### Input

| Option | Default | Notes |
|---|---|---|
| `mode` | `recent` | `recent` (walk back from yesterday), `range` (between two dates), `dates` (an explicit list) |
| `days` | `3` | How many complete days to walk back, in `recent` mode |
| `startDate` / `endDate` | - | `YYYY-MM-DD`, in `range` mode. Ranges longer than 120 days are trimmed to the most recent 120 |
| `dates` | - | One `YYYY-MM-DD` per line, in `dates` mode |
| `maxLaunchesPerDay` | `0` (all) | Keep only the top N of each day |
| `proxyConfiguration` | Apify Proxy **on** | Required in practice, see below |
| `politeDelayMs` | `1000` | One request per second |

Running with an empty input returns the last three complete days.

#### Why the proxy is on by default

Product Hunt sits behind Cloudflare, which rejects datacenter ranges on the very first
request - HTTP 429 or 403 with a challenge page, regardless of headers. Through Apify Proxy
the same run succeeds, so the Actor takes a **fresh exit IP on every attempt**: a rejection
is treated as one bad IP, not as a dead source. Leaving the proxy off is allowed but will
usually return nothing, and the log says so explicitly.

### Pricing

Pay per event:

- **Actor start** - charged once per run (one event per GB of memory; this Actor runs on 256 MB).
- **Launch** - one event per launch returned. This is the price to compare.

Nothing is charged for a result that did not come back: a date that could not be fetched
produces no items and therefore no charge.

### How it works

Product Hunt's leaderboard is a Next.js App Router page that embeds its full GraphQL payload
in the page itself. The Actor reads that payload directly over plain HTTP - no token, no
headless browser - and balances braces to recover whole launch objects.

That embedded payload is an internal format and can change without notice. If it ever does,
the Actor logs a clear warning instead of quietly returning empty data.

# Actor input Schema

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

"Recent days" walks back from yesterday. "Date range" scrapes every day between two dates. "Specific dates" scrapes only the days you list. Today is never scraped: its leaderboard is still filling up.

## `days` (type: `integer`):

Number of complete days to scrape, counting back from yesterday. Each day returns the launches that Product Hunt ranked on its daily leaderboard, typically 10 to 17.

## `startDate` (type: `string`):

First day of the range, as YYYY-MM-DD. If left empty, the range starts six days before the end date.

## `endDate` (type: `string`):

Last day of the range, as YYYY-MM-DD. Defaults to today. A range longer than 120 days is trimmed to the most recent 120.

## `dates` (type: `array`):

One date per line, as YYYY-MM-DD. Future dates are ignored.

## `maxLaunchesPerDay` (type: `integer`):

Keep only the top N ranked launches of each day. Leave at 0 to keep every ranked launch the leaderboard returns.

## `politeDelayMs` (type: `integer`):

Milliseconds between requests to Product Hunt. The default of 1000 ms (one request per second) is deliberately conservative and was measured clean over ten consecutive dates. Lower it only if you know what you are doing.

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

Apify Proxy, on by default and required in practice: Product Hunt sits behind Cloudflare, which rejects datacenter ranges outright. Every retry takes a fresh exit IP.

## Actor input object example

```json
{
  "mode": "recent",
  "days": 3,
  "startDate": "2026-07-01",
  "endDate": "2026-07-07",
  "dates": [
    "2026-07-15",
    "2026-07-16"
  ],
  "maxLaunchesPerDay": 0,
  "politeDelayMs": 1000,
  "proxyConfiguration": {
    "useApifyProxy": true
  }
}
```

# Actor output Schema

## `results` (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 = {
    "startDate": "2026-07-01",
    "endDate": "2026-07-07",
    "dates": [
        "2026-07-15",
        "2026-07-16"
    ],
    "proxyConfiguration": {
        "useApifyProxy": true
    }
};

// Run the Actor and wait for it to finish
const run = await client.actor("automia-admin/product-hunt-leaderboard-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 = {
    "startDate": "2026-07-01",
    "endDate": "2026-07-07",
    "dates": [
        "2026-07-15",
        "2026-07-16",
    ],
    "proxyConfiguration": { "useApifyProxy": True },
}

# Run the Actor and wait for it to finish
run = client.actor("automia-admin/product-hunt-leaderboard-scraper").call(run_input=run_input)

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

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

```

## CLI example

```bash
echo '{
  "startDate": "2026-07-01",
  "endDate": "2026-07-07",
  "dates": [
    "2026-07-15",
    "2026-07-16"
  ],
  "proxyConfiguration": {
    "useApifyProxy": true
  }
}' |
apify call automia-admin/product-hunt-leaderboard-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "command": "npx",
            "args": [
                "mcp-remote",
                "https://mcp.apify.com/?tools=automia-admin/product-hunt-leaderboard-scraper",
                "--header",
                "Authorization: Bearer <YOUR_API_TOKEN>"
            ]
        }
    }
}

```

## OpenAPI specification

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