Product Hunt – Products, Launches, Makers & Reviews avatar

Product Hunt – Products, Launches, Makers & Reviews

Pricing

from $1.00 / 1,000 results

Go to Apify Store
Product Hunt – Products, Launches, Makers & Reviews

Product Hunt – Products, Launches, Makers & Reviews

Extract producthunt.com data including products, launches, keyword search results, maker profiles, reviews, categories, media, social links, product websites, and optional public contact emails.

Pricing

from $1.00 / 1,000 results

Rating

0.0

(0)

Developer

Abot API

Abot API

Maintained by Community

Actor stats

0

Bookmarked

4

Total users

0

Monthly active users

4 days ago

Last modified

Share

Product Hunt Scraper: Launches, Makers, Reviews & Contact Emails

Product Hunt Scraper turns Product Hunt into structured data you can act on. Pull product launches, maker profiles and reviews by pasting Product Hunt links or searching by keyword, optionally enrich each product with the reviews already on its page and public contact emails found on its own website, then export to JSON, CSV or Excel, or read the results straight through the API.

Why This Scraper?

  • Two ways to find products. Pick keyword mode to auto-generate Product Hunt search URLs, or url mode to paste homepage, search, leaderboard, topic, collection, product, or maker profile links directly.
  • Three record types, one dataset. Product listings and single product pages, maker profiles, and (optionally) individual reviews all land in the same dataset with a rowType field to tell them apart.
  • Optional detail enrichment on demand. Turn on public contact-email discovery on each product's own website, and/or pull the reviews already published on its Product Hunt page, and only pay the enrichment surcharge on rows actually returned.
  • Record-level filters. Keep only products above a minimum review or follower count, or that expose a website or a social/source-code link, so a run returns only what you need.
  • Built for recurring runs. Incremental mode returns only new and changed products on repeat runs against the same search or URL set, and unchanged rows are not billed.
  • Resume a big pull. Point resumeFromRunId at an interrupted run or dataset and the next run skips everything it already collected, so a large crawl never restarts from zero.
  • Cost control built in. maxItems caps the dataset size and maxSearchResultsPerTerm caps how many candidates are scanned before filters apply, so a run's cost stays predictable.

Use Cases

  • Lead generation and outreach: collect maker names, product websites and public contact emails for tools in a category you sell into.
  • Market and competitor research: track which products launch or gain traction in a topic or category over time.
  • Content and newsletter curation: pull recent launches, taglines and descriptions to summarize a day's or week's top products.
  • Investor and trend scouting: filter by minimum followers or reviews to surface products gaining real traction, not just noise.
  • Directory and profile building: collect maker profiles and the full list of products each maker has shipped.

Data You Get

Sample shape: values are illustrative placeholders, not from a live record.

FieldExample
rowType"product" (also "maker", and "review" when outputReviewsAsRows is on)
id"product:sample-ai-assistant"
slug / canonicalUrl / sourceUrl"sample-ai-assistant" and the Product Hunt link to the product page
name"Sample AI Assistant"
tagline"Ship features while you sleep"
description"An AI pair programmer that opens pull requests for you."
websiteUrl"https://sample-ai-assistant.example.com"
upvotes / votesCountupvotes of the product's latest launch (350)
commentsCountcomments on the latest launch (10)
date / launchNamelatest launch date and launch title
logoUrl / images / youtubeVideoUrllogo, screenshot URLs and the launch video link, when present
shortDescription / url / websiteone-line tagline, Product Hunt product URL and the product's own website
makerlaunch makers: name, username, profile URL, avatar
websiteRawTextfirst 5,000 characters of the product's website text (only with Save website text)
followersCount / reviewsCount / averageRating1240, 18, 4.6
postsCount3 (times this product has launched on Product Hunt)
launchesCount / dayRank / weekRank / monthRank / launchDayScore / badges[]launch history and standing: launches (same as postsCount), rank of the latest launch on its daily, weekly and monthly leaderboard (1, 7, 28), its launch-day score, and top-post badges (period daily, weekly, monthly or yearly; only this product's own launches, never the sponsored product shown on the page) such as { "period": "daily", "rank": 1, "date": "2025-05-13" }
pricingType / ratingBreakdown[] / appStoreUrl / googlePlayUrl / employeeSize / fundingAmount / wasInYCombinator / isPromotedpricing model (for example "free_options"), star distribution [{ "rating": 5, "count": 37 }], Product Hunt links that redirect to the App Store and Google Play listings, company size, funding and Y Combinator flag (null when not filled in), and true when the listing page showed the product as a sponsored placement
media[] / mediaCountproduct gallery screenshot URLs
categories[][{ "name": "AI Coding Agents", "path": "/topics/ai-coding-agents", "slug": "ai-coding-agents" }]
reviews[] / reviewsExtractedembedded review objects, capped by maxReviewsPerProduct (when includeReviews is on)
harvestedEmails[]public contact emails found on websiteUrl (when enrichEmails is on)
searchContextdiscovery metadata: {"sourceType": "product"} only for a pasted product URL, plus discoveryUrl/resultPosition/keyword when the product was found via a listing or search
scrapedAtISO timestamp of the scrape
changeType / changedFields / firstSeenAt / lastSeenAtincremental mode only: "NEW", "UPDATED", "UNCHANGED", "REAPPEARED" or "EXPIRED", which fields changed, and first/last seen

Maker-profile rows (one per pasted /@username URL) carry username, headline, avatarUrl, productUrls[] and productsCount instead of the product fields above. Review rows, embedded inside a product's reviews[] by default or pushed as their own dataset rows when outputReviewsAsRows is on, carry reviewId, reviewUrl, rating, ratingMax, reviewText, positiveNotes[], negativeNotes[], reviewDate, authorName, authorUrl and authorImage, plus easeOfUseRating, reliabilityRating, valueForMoneyRating, customizationRating (1-5, when the reviewer filled them in) and viewsCount (views shown on the review card) for reviews whose details are on the page. A product's social and app links, when present, add twitterUrl, githubUrl, linkedinUrl, facebookUrl, instagramUrl, iosUrl and androidUrl alongside websiteUrl.

How to Use

  1. Pick a mode: keyword (search by term) or url (paste Product Hunt homepage, search, leaderboard, topic, collection, product, or maker profile links).
  2. Turn on the filters and enrichment you need: minimum reviews or followers, requiring a website or social link, contact-email discovery, and review extraction.
  3. Set Max items to control run size and cost, and raise Max search candidates per keyword if strict filters are narrowing results too much.
  4. Click Start, then download the dataset as JSON, CSV or Excel, or read it through the API.

Keyword search in one category:

{
"mode": "keyword",
"searchTerms": ["ai coding assistant"],
"searchCategories": ["ai-coding-agents"],
"maxItems": 10
}

Leaderboard day, with follower and website filters:

{
"mode": "url",
"startUrls": [{ "url": "https://www.producthunt.com/leaderboard/daily/2025/1/1" }],
"minFollowersCount": 50,
"websiteRequired": true,
"maxItems": 15
}

Recurring incremental run with expiry tracking (caps raised so the scan can reach the natural end):

{
"mode": "keyword",
"searchTerms": ["productivity tools"],
"incrementalMode": true,
"emitExpired": true,
"maxItems": 500,
"maxSearchResultsPerTerm": 500
}

Paste a product and a maker profile directly, with enrichment on:

{
"mode": "url",
"startUrls": [
{ "url": "https://www.producthunt.com/products/sample-ai-assistant" },
{ "url": "https://www.producthunt.com/@sample_maker" }
],
"enrichEmails": true,
"includeReviews": true
}

URL shapes

URL mode accepts: homepage, search (/search?q=..., &page=N is passed through), daily/weekly/monthly leaderboards, topics index and topic pages (?page=N is honoured), categories index and category pages, collections index and single collections, product pages (legacy /posts/<slug> links are mapped to /products/<slug>; producthunt.com without www works; a product's /reviews and /launches pages are treated as the same product, so a product pasted in several forms yields one row, one change check and one detail-enrichment charge per run), and maker profiles /@handle. Search result pages are rendered server-side with the first page of results only, so &page=N on a search URL currently returns the same products as page 1; use topic or category pages to go deeper. The order search parameter has no verified effect and is not supported. Maker profiles are behind an access challenge on some connections; when one cannot be read the run logs a warning for that URL and returns no row for it.

Behaviour change: if you run URL mode without setting startUrls, the actor now scrapes the built-in list of example URLs, one per shape above, instead of only the homepage. Set startUrls explicitly to control the scope. Custom categories accept a category name as shown on the Product Hunt categories page (for example AI Coding Agents) as well as a slug; an unknown name stops the run with an error, and a categories page that cannot be loaded stops it with a separate connection error.

Run it from your code

Python:

from apify_client import ApifyClient
client = ApifyClient("<YOUR_APIFY_TOKEN>")
run = client.actor("abotapi/product-hunt-launches-scraper").call(run_input={"mode": "keyword", "searchTerms": ["ai"], "maxItems": 10})
for item in client.dataset(run["defaultDatasetId"]).iterate_items():
print(item["rowType"], item.get("name"))

JavaScript:

import { ApifyClient } from 'apify-client';
const client = new ApifyClient({ token: '<YOUR_APIFY_TOKEN>' });
const run = await client.actor('abotapi/product-hunt-launches-scraper').call({ mode: 'keyword', searchTerms: ['ai'], maxItems: 10 });
const { items } = await client.dataset(run.defaultDatasetId).listItems();

Or connect it to Make, Zapier, n8n, Google Sheets or webhooks from the Integrations tab.

How maxSearchResultsPerTerm and maxItems shape a run

Keyword and listing URLs are expanded into candidate product links first, then each candidate is fetched and run through the record-level filters (minReviewsCount, minFollowersCount, websiteRequired, socialLinkRequired). maxSearchResultsPerTerm bounds how many candidates are scanned before filtering; left empty, the actor scans roughly five candidates per row you asked for (at least 20). maxItems then caps how many rows actually get pushed after filtering and enrichment. If a strict filter combination returns fewer rows than expected, raise maxSearchResultsPerTerm so more candidates get a chance to pass.

Resume and recurring updates

Two different features, both optional and off by default:

  • Resume (resumeFromRunId) continues ONE specific interrupted run or dataset: paste its run or dataset id and this run skips every row already collected there, so you don't pay twice.
  • Incremental mode (incrementalMode) is for recurring runs over the SAME search or URL set (e.g. daily). Each tracked product is classified NEW, UPDATED (with changedFields), or UNCHANGED (suppressed and not billed unless emitUnchanged is on). REAPPEARED only ever appears for a product whose stored state was already marked absent by an earlier complete scan that had emitExpired on; it never happens on a first run, and it is never the default outcome for a returning product. EXPIRED rows are synthesized only when emitExpired is on AND the current run reaches the natural end of every tracked source, uncapped by maxItems or maxSearchResultsPerTerm and without resumeFromRunId in use; an interrupted or capped scan cannot tell "gone" apart from "not reached yet", so it leaves the previous state untouched instead. Scrape timestamps, launch vote and comment counters, leaderboard ranks (dayRank, weekRank, monthRank), launchDayScore, the star distribution counts (ratingBreakdown), the sponsored-placement flag (isPromoted), review view counts and review sub-ratings, rotating image URL query strings and the order of harvested emails never count as a change, and ignoreFieldsForChanges excludes further fields from change detection (they stay in the output). A pasted listing URL that starts at ?page=2 or later is a partial scan and never produces EXPIRED rows. stateKey names or shares a monitoring campaign; left empty, the actor derives one automatically from the search/URL set and the filter/enrichment settings, so differently configured runs never mix state. Only product rows are classified. Maker rows are never suppressed; review rows are returned only alongside their parent product, so a review's rows are hidden whenever the parent product is suppressed as UNCHANGED.

Output views

The dataset has ready-made views, also linked from the run's Output tab: overview, products, makers, reviews (review rows from outputReviewsAsRows), embeddedReviews (one row per review embedded in a product) and changes (incremental mode: changeType and changedFields). A run summary is stored under the OUTPUT key of the key-value store.

Send results into your apps (MCP connectors)

Optionally pipe the scraped results into the apps you already use, via Model Context Protocol (MCP) connectors. This is an extra delivery step after the scrape: the Apify dataset is never changed.

What gets written to the connector: a condensed, human-readable summary of each record, not the full JSON. Each item becomes one entry with a title and its key fields flattened to plain text. The complete record always stays in the Apify dataset.

  1. Authorize a connector once under Apify → Settings → Integrations (Notion, Linear, Airtable, or Apify).
  2. Select it in the "Pipe results into your apps" input field. (If the picker is empty, you haven't authorized a connector yet.)
  3. For Notion, also set notionParentPageUrl to the page where items should be created.

The connection is mediated by Apify's MCP proxy, so this actor never sees your third-party credentials. Leave the field empty to skip.

Input Parameters

ParameterTypeDefaultDescription
modestringkeywordkeyword (generate searches) or url (paste Product Hunt links).
startUrlsarrayone example of each supported URL shape (see URL shapes)Product Hunt URLs to scrape directly (url mode).
searchTermsarrayno default (prefill: ["ai"])Keywords to search (keyword mode); each expands into product rows.
searchSortstringrelevanceSort applied to generated keyword search URLs: relevance, popular, or newest.
searchCategoriesarray[]Restrict generated keyword searches to one or more listed Product Hunt categories.
searchCategorySlugsarrayno defaultAdvanced: custom Product Hunt category slugs not in the list above.
enrichEmailsbooleantrueCheck each product's own website for public contact emails.
includeReviewsbooleantrueInclude review summaries published on each product's page.
outputReviewsAsRowsbooleanfalseAlso save each extracted review as its own dataset row.
maxReviewsPerProductinteger20Upper bound on review rows per product (0 omits review details; the maximum is 100). The product page itself embeds only about 3 reviews, so the actor loads the product's separate reviews pages (ten reviews each, so roughly one extra page load for every ten reviews wanted) until the cap or the product's own review count is reached; if a reviews page cannot be loaded, the reviews already collected are kept. Because review lists are now longer than before, the first incremental run after this update can report products with more reviews as updated. Turning Include reviews off empties reviews[] but keeps reviewsCount.
maxItemsinteger20Hard cap on total dataset rows.
maxSearchResultsPerTermintegerno default (falls back to max(maxItems × 5, 20))Total candidate products scanned across all keywords and URLs combined, before filters apply.
minReviewsCountintegerno defaultKeep only products with at least this many Product Hunt reviews.
minFollowersCountintegerno defaultKeep only products with at least this many Product Hunt followers.
websiteRequiredbooleanfalseKeep only products that expose an external website URL.
socialLinkRequiredbooleanfalseKeep only products that expose a social or source-code link.
scrapeMakersbooleantrueInclude launch makers on each product row. No extra requests.
saveWebsiteContentbooleanfalseSave the first 5,000 characters of each product website's text in websiteRawText.
archiveDatestringno defaultScrape that day's leaderboard (YYYY-MM-DD).
archiveWeekintegerno defaultScrape a weekly leaderboard (the year defaults to the current one).
archiveYearintegerno defaultYear for archiveWeek; the yearly leaderboard when only the year is set.
filterobject{}minVotes, maxVotes on latest-launch upvotes; topNProducts caps the product count.
resumeFromRunIdstringno defaultContinue one interrupted run or dataset without re-collecting or re-billing its rows.
incrementalModebooleanfalseTurn on recurring monitoring: classify products as NEW / UPDATED / UNCHANGED / REAPPEARED / EXPIRED.
stateKeystringno defaultName or share an incremental-mode monitoring campaign.
ignoreFieldsForChangesarray[]Incremental mode only: field names (top-level or nested, e.g. reviews, media) that never make a product UPDATED. They are still returned.
emitUnchangedbooleanfalseAlso return (and bill) products unchanged since the last incremental run.
emitExpiredbooleanfalseAlso return (and bill) products no longer found, after a complete scan.
proxyobjectno default (prefill: Apify Proxy on)Connection settings.
mcpConnectorsarrayno defaultOptional: send a summary of each record to apps you authorized under Integrations.
notionParentPageUrlstringno defaultNotion connector only: page under which records are created.
maxNotifyListingsinteger50Cap on items written to each connector per run.

Output Example

Sample shape: values are illustrative placeholders, not from a live record.

{
"rowType": "product",
"id": "product:sample-ai-assistant",
"sourceUrl": "https://www.producthunt.com/products/sample-ai-assistant",
"canonicalUrl": "https://www.producthunt.com/products/sample-ai-assistant",
"slug": "sample-ai-assistant",
"name": "Sample AI Assistant",
"tagline": "Ship features while you sleep",
"description": "An AI pair programmer that opens pull requests for you.",
"logoUrl": "https://ph-files.example.com/sample-logo.png",
"websiteUrl": "https://sample-ai-assistant.example.com",
"twitterUrl": "https://twitter.com/sampleaiassistant",
"githubUrl": "https://github.com/sample-org/sample-ai-assistant",
"votesCount": 350,
"upvotes": 350,
"commentsCount": 10,
"followersCount": 1240,
"reviewsCount": 18,
"postsCount": 3,
"media": [
{ "type": "image", "url": "https://ph-files.example.com/shot-1.png", "alt": "Product screenshot", "width": 1280, "height": 800 }
],
"mediaCount": 1,
"categories": [
{ "name": "AI Coding Agents", "path": "/topics/ai-coding-agents", "slug": "ai-coding-agents" }
],
"reviews": [
{
"rowType": "review",
"id": "review:sample-ai-assistant:https://www.producthunt.com/products/sample-ai-assistant#review-1",
"productSlug": "sample-ai-assistant",
"productUrl": "https://www.producthunt.com/products/sample-ai-assistant",
"reviewId": "https://www.producthunt.com/products/sample-ai-assistant#review-1",
"reviewUrl": "https://www.producthunt.com/products/sample-ai-assistant#review-1",
"rating": 5,
"ratingMax": 5,
"reviewText": "Cut our release time in half.",
"positiveNotes": ["Fast setup", "Great support"],
"negativeNotes": [],
"reviewDate": "2026-01-14",
"dateModified": "2026-01-14",
"authorName": "Jordan Reviewer",
"authorUrl": "https://www.producthunt.com/@jordan_reviewer",
"authorImage": "https://ph-avatars.example.com/jordan.png",
"scrapedAt": "2026-01-20T09:15:00+00:00"
}
],
"reviewsExtracted": 1,
"averageRating": 4.6,
"searchContext": {
"sourceType": "search",
"discoveryUrl": "https://www.producthunt.com/search?q=ai%20assistant",
"resultPosition": 3,
"keyword": "ai assistant"
},
"scrapedAt": "2026-01-20T09:15:00+00:00",
"harvestedEmails": ["hello@sample-ai-assistant.example.com"]
}

Plan Requirement

Apify Proxy is used automatically unless you turn it off. Listing, search, leaderboard, topic, category, collection and product pages load over the default datacenter connection, so a paid plan with default proxy settings is enough for these shapes. Maker profile pages (/@handle) sit behind an access challenge that the datacenter connection does not pass; for those, choose the Residential group under 🌐 Proxy & connection (residential access requires a paid Apify plan, and clearing the challenge on residential has not been verified). Apify free plans do not include any Apify Proxy, so a free-plan run falls back to a backup connection and logs:

The selected connection is unavailable to this run. Apify free plans do not include residential proxies. Continuing on a backup connection; some pages may still be unavailable.

and, per page served that way, Served over the backup connection (the default connection was unavailable). If nothing could be read, the run fails with one of these messages instead of returning an empty dataset silently:

  • The proxy connection was refused for this account, so no page could be read. Your Apify plan does not include proxy access; a paid plan is required.
  • No results: residential proxies are unavailable on this run (Apify free plans do not include them), and the backup connection could not load the requested Product Hunt pages.
  • Could not load any results page (the requests failed), so nothing was collected. This is a connection problem, not an empty search. Please try again later.

A maker URL that cannot be read logs a warning naming that URL and returns no row for it.

FAQ

How much does it cost?

You are charged for three events: apify-actor-start once per run, apify-default-dataset-item for each record pushed to the dataset, and detail-enrichment once per pushed product row that was enriched, when email checking or review extraction is switched on (both are on by default); filtered-out rows and rows suppressed as unchanged in incremental mode are never charged for enrichment. The Pricing tab shows the current rates. Use Max items to cap the cost of any run.

This actor collects only publicly available Product Hunt pages. You are responsible for how you use the data: follow Product Hunt's terms and the privacy laws that apply to you, especially around maker names and public contact emails, and get legal advice if you plan commercial redistribution.

Can I get only new or changed launches on a schedule?

Yes. Schedule the actor from the Schedules tab and turn on Incremental mode. Repeat runs against the same search or URL set then return only new and updated products; unchanged ones are suppressed and not billed unless you turn on Emit unchanged.

What do votesCount, upvotes and commentsCount mean?

Product Hunt counts votes and comments per launch. The actor reports the figures of the product's latest launch. They change constantly, so they are left out of change detection in Incremental mode and never mark a product as UPDATED on their own.

Why did my run return an empty dataset instead of failing?

A page that fails to load, or a product page the actor could not read after retries, is logged and skipped rather than failing the whole run: you still get every product that did load. The run stops outright in three cases: an unreadable resumeFromRunId; turning on Incremental mode with resumeFromRunId against a search that already has saved incremental state; or invalid input, such as URL mode with no startUrls, keyword mode with no searchTerms, or an unrecognized mode. Each case gives a clear error message telling you what to change.

Can I use it with AI agents or MCP?

Yes. Call it from any Apify integration or MCP client, and use the connector field to push results into Notion, Linear or Airtable.

🔗 Want more leads data?

Pair this actor with these related scrapers from the same team:

📇 BetaList Scraper
Scrape BetaList.com startup profiles with founder and contact enrichment. Extract startup...
📇 Ycombinator
Pull every ycombinator.com company across every batch, with founders, social URLs...
📇 2GIS
Extract business and place data from 2GIS.com at scale. Get names, addresses, phones...
🛒 Dealroom.net Scraper
Scrape Dealroom.net market maps, company lookup results, live signals, and newly founded...
🛒 ProductReview.com.au Scraper
Scrape ProductReview.com.au products, businesses and customer reviews. Search by...
🛒 Naver Shopping Scraper
Scrape Naver Shopping products by Korean or English keyword, or by URL. Returns 190+...

👉 Browse all abotapi scrapers

💬 Support

  • 🐞 Found a bug or a missing field? Open a ticket on the Issues tab. We usually reply within hours.
  • 🛠️ Need another site, extra fields or a private build? Email contact@abotapi.com.
  • ⭐ Enjoying it? A quick review on the actor page helps other users find it.