# Product Hunt Launch Monitor — Products & Upvotes (`northglasslabs/producthunt-scraper`) Actor

Collect Product Hunt's current ranked or newest launch listings. Export product names, taglines, URLs, visible upvotes, makers, topics, and dates, with optional local filtering.

- **URL**: https://apify.com/northglasslabs/producthunt-scraper.md
- **Developed by:** [North Glass Labs](https://apify.com/northglasslabs) (community)
- **Categories:** Social media
- **Stats:** 2 total users, 0 monthly users, 89.7% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $2.34 / 1,000 result storeds

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/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 Daily Launch Monitor & Scraper

Monitor the products visible on Product Hunt's **current server-rendered ranked or newest listing**. Get structured launch names, taglines, Product Hunt URLs, displayed upvotes, topics, and detail-page metadata when available.

Use it for **daily launch monitoring**, **startup research**, and **product discovery** without maintaining a browser scraper.

### What this Actor does

1. Fetches the current ranked homepage (`popular` or `top`) or `/newest` (`newest`).
2. Parses only verified launch cards from that server-rendered listing.
3. Optionally applies `searchQuery` as a **local filter** over each visible product's name, tagline, and topics.
4. Visits each selected product page and enriches the listing record when Product Hunt exposes additional metadata.
5. Pushes one structured item per product to the default dataset.

#### Scope and limitations

- This is **not a full-catalog Product Hunt search**. Product Hunt's dedicated search results are currently client-rendered, so this Actor only filters products present in the current ranked/newest server-rendered listing.
- `popular` and `top` currently select the same ranked homepage; they do not represent separate historical or all-time datasets.
- Product Hunt may omit upvotes, topics, maker profiles, or launch dates. Missing lists are returned as `[]`; missing text/date values may be `null`; unavailable upvotes are `0`.
- `makers` contains Product Hunt display names and profile URLs when those links are present. The Actor **does not return email addresses, phone numbers, or other maker contact data**.
- A filter with no match in the verified current listing returns an empty dataset. A blocked or unparseable listing fails instead of reporting a false-success empty run.

### Input

| Field | Type | Default | Description |
|---|---|---:|---|
| `searchQuery` | string | `""` | Optional case-insensitive local filter over visible names, taglines, and topics. |
| `maxResults` | integer | `50` | Maximum products to enrich and save; range 1–500. |
| `sortBy` | string | `popular` | `newest` fetches `/newest`; `popular` and `top` fetch the ranked homepage. |

The ranked homepage is the proven default. Product Hunt controls `/newest`, and its availability can vary or return an upstream 404; the Actor fails visibly rather than substituting ranked products for an explicitly requested newest listing.

#### Daily monitoring input

```json
{
  "searchQuery": "",
  "maxResults": 50,
  "sortBy": "popular"
}
```

#### Focused startup-research input

```json
{
  "searchQuery": "productivity",
  "maxResults": 20,
  "sortBy": "popular"
}
```

Because filtering is local to the current listing, a phrase such as `"AI tools"` only matches if that exact phrase appears in a visible name, tagline, or topic. For broader discovery, use a short keyword such as `"AI"` or `"productivity"`.

### Output

Each default-dataset item follows this contract:

| Field | Type | Meaning |
|---|---|---|
| `name` | string | Product name shown by Product Hunt. |
| `tagline` | string or null | Product tagline or detail-page description. |
| `url` | string | Absolute Product Hunt product/post URL. |
| `upvotes` | integer | Displayed vote/rating count when found; otherwise `0`. |
| `makers` | array | Zero or more `{name, profile}` objects from Product Hunt profile links. |
| `topics` | array of strings | Product Hunt topic labels when found. |
| `launchDate` | string or null | Date text/ISO value exposed on the product page when found. |

### API recipes

Set your Apify token and Actor identifier first. `ACTOR_ID` accepts the `username~actor-name` format.

```bash
export APIFY_TOKEN="YOUR_APIFY_TOKEN"
export ACTOR_ID="YOUR_USERNAME~producthunt-scraper"
```

The synchronous endpoint below starts a run, waits for completion, and returns default-dataset items as JSON. For large runs, use Apify's asynchronous run endpoint instead to avoid client timeout limits.

#### cURL

```bash
curl --fail --silent --show-error \
  --request POST \
  --header 'Content-Type: application/json' \
  --data '{"searchQuery":"productivity","maxResults":20,"sortBy":"popular"}' \
  "https://api.apify.com/v2/acts/${ACTOR_ID}/run-sync-get-dataset-items?token=${APIFY_TOKEN}"
```

#### Python

```python
import os
import requests

actor_id = os.environ["ACTOR_ID"]
token = os.environ["APIFY_TOKEN"]
response = requests.post(
    f"https://api.apify.com/v2/acts/{actor_id}/run-sync-get-dataset-items",
    params={"token": token},
    json={"searchQuery": "AI", "maxResults": 20, "sortBy": "newest"},
    timeout=300,
)
response.raise_for_status()
items = response.json()
print(f"Received {len(items)} current-listing products")
```

#### JavaScript (Node.js 18+)

```javascript
const actorId = process.env.ACTOR_ID;
const token = process.env.APIFY_TOKEN;
const endpoint = `https://api.apify.com/v2/acts/${actorId}/run-sync-get-dataset-items?token=${token}`;

const response = await fetch(endpoint, {
  method: 'POST',
  headers: { 'content-type': 'application/json' },
  body: JSON.stringify({ searchQuery: '', maxResults: 50, sortBy: 'popular' }),
});
if (!response.ok) throw new Error(`Apify request failed: ${response.status}`);
const items = await response.json();
console.log(`Received ${items.length} current-listing products`);
```

#### n8n HTTP Request

Create an **HTTP Request** node with:

- **Method:** `POST`
- **URL:** `https://api.apify.com/v2/acts/YOUR_USERNAME~producthunt-scraper/run-sync-get-dataset-items`
- **Query parameter:** `token` = your Apify API token (store it in an n8n credential or environment variable)
- **Send Body:** enabled
- **Body Content Type:** JSON
- **JSON Body:**

```json
{
  "searchQuery": "",
  "maxResults": 50,
  "sortBy": "popular"
}
```

The node output is the returned array of dataset items. Schedule the workflow daily, then connect item-list, database, spreadsheet, Slack, or email nodes for your monitoring workflow. Keep the token out of exported workflow JSON when sharing it.

### Practical workflows

- **Daily launch digest:** schedule `sortBy: "newest"` with an empty filter and compare URLs with yesterday's stored records.
- **Startup research:** run a short topic keyword against the current ranked listing, then review taglines, topics, and Product Hunt pages.
- **Product discovery feed:** save the newest visible launches to a sheet/database and deduplicate on `url`.
- **Category pulse:** schedule separate runs for short terms such as `AI`, `developer`, or `productivity`; remember each term filters only that run's current listing.

The Actor returns a snapshot, not change history. Persist datasets externally or in your workflow if you need day-over-day tracking.

### Cost and runtime

The Actor fetches one listing page, then fetches up to `maxResults` product pages sequentially with a one-second pause between products. Higher `maxResults` generally means a longer run and more platform resource usage.

Your actual charge depends on the pricing and platform-usage terms displayed on the Actor's current Apify Store page and your Apify plan. Check that page before running; this README does not assume a fixed per-run or per-result price. Start with `maxResults: 10` or `20` to measure runtime and cost for your use case, then increase it if needed.

### Reliability notes

Product Hunt can change its HTML or return security challenges. The Actor restricts discovery to verified listing-card structures and excludes review/footer links. If no verified cards can be parsed, it raises an error rather than silently emitting unrelated products or an empty dataset.

# Actor input Schema

## `searchQuery` (type: `string`):

Optional case-insensitive local filter over product names, taglines, and topics in the current listing. This is not a full-catalog Product Hunt search.

## `maxResults` (type: `integer`):

Maximum number of matching products to enrich and save. Product pages are fetched sequentially, so larger values take longer.

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

Ranked fetches Product Hunt's server-rendered homepage. Newest requests /newest, whose availability can vary and may return an upstream 404.

## Actor input object example

```json
{
  "searchQuery": "",
  "maxResults": 20,
  "sortBy": "popular"
}
```

# 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 = {
    "searchQuery": "",
    "maxResults": 20,
    "sortBy": "popular"
};

// Run the Actor and wait for it to finish
const run = await client.actor("northglasslabs/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 = {
    "searchQuery": "",
    "maxResults": 20,
    "sortBy": "popular",
}

# Run the Actor and wait for it to finish
run = client.actor("northglasslabs/producthunt-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 '{
  "searchQuery": "",
  "maxResults": 20,
  "sortBy": "popular"
}' |
apify call northglasslabs/producthunt-scraper --silent --output-dataset

```

## MCP server setup

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

```

## OpenAPI specification

Download the OpenAPI definition: https://api.apify.com/v2/acts/2Pf98qiUM6L7NluVZ/builds/I3NUrJIReGjTtEkUp/openapi.json
