Get a launch's comment threads
Pull the comment threads on a launch — the maker's own notes, the questions, and the feedback launch day produces. Replies come back nested underneath their parent comment rather than flattened into one list, so walk comments[].replies recursively. Sort by score, date or votes, and page through with a cursor.
/product-comments Launches https://api.fetchlayer.dev/producthunt/product-comments Headers
Authorization string required Bearer token — your FetchLayer API key.
Parameters
product string required Product slug, launch slug, or any Product Hunt product or launch URL.
launch string optional A specific launch, instead of the product's most recent one.
limit number optional Maximum comments returned (max 300), or -1 for everything available. Counts replies too. (default: 30)
pageSize number optional Comment threads fetched per page (max 50). (default: 10)
sortBy string optional SCORE, DATE, DATE_DESC, VOTES, or DEFAULT. (default: SCORE)
pages number optional Pages of results to collect in one request (max 100), or -1 for the maximum allowed. Each page walked counts as one request. (default: 1)
cursor string optional Resume from a previous response's nextCursor.
delayMs number optional Milliseconds to wait between pages (max 30000).
format string optional json or markdown. Markdown returns the same result rendered as text. (default: json)
timeoutMs number optional Per-request time limit in milliseconds (max 600000).
Response Fields
product-comments
Get a launch's comment threads
launchSlug string The launch the comments belong to.
launchName string | null Name of that launch.
commentsCount number | null Every comment on the launch, as Product Hunt counts them.
threadCount number | null Top-level threads on the launch.
comments object[] Top-level threads. Each one carries its replies nested underneath in comments[].replies — the tree is not flattened.
comments[].body string | null The comment text with the markup removed. bodyHtml carries it as posted.
comments[].author object | null Who wrote it: username, name and avatar.
comments[].badges string[] Labels shown beside the author, such as "maker".
comments[].votes number | null Upvotes on the comment.
comments[].isPinned boolean Whether the comment is pinned to the top of the thread.
comments[].repliesCount number | null How many replies the comment has, which can exceed the number nested in replies when a walk stopped early.
comments[].replies object[] Replies, in the same shape, nested to whatever depth the thread reaches.
returnedCount number Comments in this response, replies included.
pagesScraped number Pages actually collected. Each page counts as one request against your plan.
pagesRequested number Pages the request asked for.
nextCursor string | null Pass back as cursor to continue, or null when the listing is exhausted.
hasNextPage boolean Whether more results are available beyond this response.
requestedUrl string The Product Hunt page this result corresponds to.
scrapedAt string ISO timestamp the result was collected at.
notes string[] Read this. Caveats about this specific result — a walk that stopped early, an upstream ceiling, or promoted entries that were dropped. An empty array means nothing was held back.
blocked boolean Always false on a successful response.
Request
curl -X POST "https://api.fetchlayer.dev/producthunt/product-comments" \
-H "Authorization: Bearer ss-your-key" \
-H "Content-Type: application/json" \
-d '{"product":"notion","sortBy":"SCORE","limit":50,"pageSize":20}'Response
{
"launchSlug": "notion-3-0",
"commentsCount": 312,
"threadCount": 128,
"returnedCount": 50,
"hasNextPage": true,
"notes": [
"Reply walk stopped at depth 3 on 2 threads."
],
"comments": [
{
"body": "Congrats on the launch! How does this handle offline edits?",
"author": {
"username": "jane"
},
"badges": [],
"votes": 24,
"repliesCount": 2,
"replies": [
{
"body": "Offline edits sync on reconnect.",
"author": {
"username": "ivan"
},
"badges": [
"maker"
],
"replies": []
}
]
}
]
}