Product Hunt – Products, Launches, Makers & Reviews
Pricing
from $1.00 / 1,000 results
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
Maintained by CommunityActor stats
0
Bookmarked
4
Total users
0
Monthly active users
4 days ago
Last modified
Categories
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
rowTypefield 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
resumeFromRunIdat 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.
maxItemscaps the dataset size andmaxSearchResultsPerTermcaps 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.
| Field | Example |
|---|---|
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 / votesCount | upvotes of the product's latest launch (350) |
commentsCount | comments on the latest launch (10) |
date / launchName | latest launch date and launch title |
logoUrl / images / youtubeVideoUrl | logo, screenshot URLs and the launch video link, when present |
shortDescription / url / website | one-line tagline, Product Hunt product URL and the product's own website |
maker | launch makers: name, username, profile URL, avatar |
websiteRawText | first 5,000 characters of the product's website text (only with Save website text) |
followersCount / reviewsCount / averageRating | 1240, 18, 4.6 |
postsCount | 3 (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 / isPromoted | pricing 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[] / mediaCount | product gallery screenshot URLs |
categories[] | [{ "name": "AI Coding Agents", "path": "/topics/ai-coding-agents", "slug": "ai-coding-agents" }] |
reviews[] / reviewsExtracted | embedded review objects, capped by maxReviewsPerProduct (when includeReviews is on) |
harvestedEmails[] | public contact emails found on websiteUrl (when enrichEmails is on) |
searchContext | discovery metadata: {"sourceType": "product"} only for a pasted product URL, plus discoveryUrl/resultPosition/keyword when the product was found via a listing or search |
scrapedAt | ISO timestamp of the scrape |
changeType / changedFields / firstSeenAt / lastSeenAt | incremental 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
- Pick a mode:
keyword(search by term) orurl(paste Product Hunt homepage, search, leaderboard, topic, collection, product, or maker profile links). - Turn on the filters and enrichment you need: minimum reviews or followers, requiring a website or social link, contact-email discovery, and review extraction.
- Set Max items to control run size and cost, and raise Max search candidates per keyword if strict filters are narrowing results too much.
- 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 ApifyClientclient = 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 classifiedNEW,UPDATED(withchangedFields), orUNCHANGED(suppressed and not billed unlessemitUnchangedis on).REAPPEAREDonly ever appears for a product whose stored state was already marked absent by an earlier complete scan that hademitExpiredon; it never happens on a first run, and it is never the default outcome for a returning product.EXPIREDrows are synthesized only whenemitExpiredis on AND the current run reaches the natural end of every tracked source, uncapped bymaxItemsormaxSearchResultsPerTermand withoutresumeFromRunIdin 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, andignoreFieldsForChangesexcludes further fields from change detection (they stay in the output). A pasted listing URL that starts at?page=2or later is a partial scan and never producesEXPIREDrows.stateKeynames 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 asUNCHANGED.
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.
- Authorize a connector once under Apify → Settings → Integrations (Notion, Linear, Airtable, or Apify).
- Select it in the "Pipe results into your apps" input field. (If the picker is empty, you haven't authorized a connector yet.)
- For Notion, also set
notionParentPageUrlto 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
| Parameter | Type | Default | Description |
|---|---|---|---|
mode | string | keyword | keyword (generate searches) or url (paste Product Hunt links). |
startUrls | array | one example of each supported URL shape (see URL shapes) | Product Hunt URLs to scrape directly (url mode). |
searchTerms | array | no default (prefill: ["ai"]) | Keywords to search (keyword mode); each expands into product rows. |
searchSort | string | relevance | Sort applied to generated keyword search URLs: relevance, popular, or newest. |
searchCategories | array | [] | Restrict generated keyword searches to one or more listed Product Hunt categories. |
searchCategorySlugs | array | no default | Advanced: custom Product Hunt category slugs not in the list above. |
enrichEmails | boolean | true | Check each product's own website for public contact emails. |
includeReviews | boolean | true | Include review summaries published on each product's page. |
outputReviewsAsRows | boolean | false | Also save each extracted review as its own dataset row. |
maxReviewsPerProduct | integer | 20 | Upper 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. |
maxItems | integer | 20 | Hard cap on total dataset rows. |
maxSearchResultsPerTerm | integer | no default (falls back to max(maxItems × 5, 20)) | Total candidate products scanned across all keywords and URLs combined, before filters apply. |
minReviewsCount | integer | no default | Keep only products with at least this many Product Hunt reviews. |
minFollowersCount | integer | no default | Keep only products with at least this many Product Hunt followers. |
websiteRequired | boolean | false | Keep only products that expose an external website URL. |
socialLinkRequired | boolean | false | Keep only products that expose a social or source-code link. |
scrapeMakers | boolean | true | Include launch makers on each product row. No extra requests. |
saveWebsiteContent | boolean | false | Save the first 5,000 characters of each product website's text in websiteRawText. |
archiveDate | string | no default | Scrape that day's leaderboard (YYYY-MM-DD). |
archiveWeek | integer | no default | Scrape a weekly leaderboard (the year defaults to the current one). |
archiveYear | integer | no default | Year for archiveWeek; the yearly leaderboard when only the year is set. |
filter | object | {} | minVotes, maxVotes on latest-launch upvotes; topNProducts caps the product count. |
resumeFromRunId | string | no default | Continue one interrupted run or dataset without re-collecting or re-billing its rows. |
incrementalMode | boolean | false | Turn on recurring monitoring: classify products as NEW / UPDATED / UNCHANGED / REAPPEARED / EXPIRED. |
stateKey | string | no default | Name or share an incremental-mode monitoring campaign. |
ignoreFieldsForChanges | array | [] | Incremental mode only: field names (top-level or nested, e.g. reviews, media) that never make a product UPDATED. They are still returned. |
emitUnchanged | boolean | false | Also return (and bill) products unchanged since the last incremental run. |
emitExpired | boolean | false | Also return (and bill) products no longer found, after a complete scan. |
proxy | object | no default (prefill: Apify Proxy on) | Connection settings. |
mcpConnectors | array | no default | Optional: send a summary of each record to apps you authorized under Integrations. |
notionParentPageUrl | string | no default | Notion connector only: page under which records are created. |
maxNotifyListings | integer | 50 | Cap 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.
Is it legal to scrape Product Hunt?
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+... |
💬 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.