Integration Guide
How to Find the Best Day to Launch on Product Hunt (With Real Data)
'Does your Product Hunt launch day actually matter?' gets asked constantly, and answered with opinions. Here's how to pull the actual leaderboard history and check for yourself — plus how to watch a competitor's launch in real time.
Written by Alex P.
- Product Hunt
- product launch
- launch strategy
- leaderboard
- competitor tracking
“Does your Product Hunt launch day actually matter? Here’s what I found” and “I probed 2,291 Product Hunt launches from 2023-2025” are the kind of posts that do well on r/ProductHunters and r/SideProject — because the actual question, “what’s the best day to launch,” gets answered with opinions and anecdotes from people who launched once or twice. The leaderboard itself is a public, structured record going back years. Nobody needs to guess.
This builds the dataset yourself, and a second, smaller thing the same endpoint is good for: watching a specific competitor’s launch unfold in real time instead of refreshing the page.
Pull a day’s leaderboard
const API_KEY = process.env.FETCHLAYER_API_KEY;
async function getDailyLeaderboard(date) {
const res = await fetch('https://api.fetchlayer.dev/producthunt/leaderboard', {
method: 'POST',
headers: { Authorization: `Bearer ${API_KEY}`, 'Content-Type': 'application/json' },
body: JSON.stringify({ period: 'daily', date, limit: 30 }),
});
const { entries } = await res.json();
return entries; // promoted placements already removed — this is the organic ranking
}
entries comes back with promoted (paid) placements already filtered out, so what you get is the actual competitive ranking, not a mix of paid and organic. Each entry carries rank and a nested launch object with upvotes, commentsCount, launchDate, productSlug, and topics — everything needed to build a day-of-week comparison.
Building the day-of-week dataset
async function collectDays(startDate, numDays) {
const results = [];
const date = new Date(startDate);
for (let i = 0; i < numDays; i++) {
const dateStr = date.toISOString().slice(0, 10);
const entries = await getDailyLeaderboard(dateStr);
const dayOfWeek = date.toLocaleDateString('en-US', { weekday: 'long' });
const topUpvotes = entries[0]?.launch?.upvotes ?? 0;
const top10Avg = entries.slice(0, 10).reduce((sum, e) => sum + (e.launch?.upvotes ?? 0), 0) / 10;
results.push({ date: dateStr, dayOfWeek, launchCount: entries.length, topUpvotes, top10Avg });
date.setDate(date.getDate() + 1);
}
return results;
}
function summarizeByDayOfWeek(days) {
const byDay = {};
for (const d of days) {
if (!byDay[d.dayOfWeek]) byDay[d.dayOfWeek] = { count: 0, totalTop10Avg: 0, totalLaunches: 0 };
byDay[d.dayOfWeek].count++;
byDay[d.dayOfWeek].totalTop10Avg += d.top10Avg;
byDay[d.dayOfWeek].totalLaunches += d.launchCount;
}
return Object.entries(byDay).map(([day, stats]) => ({
day,
avgTop10Upvotes: (stats.totalTop10Avg / stats.count).toFixed(1),
avgLaunchCount: (stats.totalLaunches / stats.count).toFixed(1),
}));
}
Read the output as “how much competition and attention each day has historically drawn,” not as a guaranteed formula — a launch’s own quality still dominates its outcome. What this actually tells you: a day with a high avgLaunchCount and a high avgTop10Upvotes is a crowded, well-attended day (more total attention, but more to beat); a quieter day is easier to top but has a smaller ceiling. Which trade-off is right depends on whether you’re optimizing for “won the day” or “reached the most people.”
Widening the sweep with pages
Thirty days is one request per day at limit: 30. For a longer historical pull, pages walks several pages of the same period in one call rather than requiring a loop of daily requests — useful for weekly or monthly boards where you want deeper coverage of a single period:
async function getMonthlyLeaderboardDeep(year, month) {
const res = await fetch('https://api.fetchlayer.dev/producthunt/leaderboard', {
method: 'POST',
headers: { Authorization: `Bearer ${API_KEY}`, 'Content-Type': 'application/json' },
body: JSON.stringify({ period: 'monthly', year, month, pages: 5, limit: 250 }),
});
return (await res.json()).entries;
}
sortBy (DAILY_RANK, WEEKLY_RANK, MONTHLY_RANK, YEARLY_RANK, VOTES, or SCORE) changes the ordering within whatever period you’re pulling — useful for pulling a month sorted by raw VOTES rather than Product Hunt’s own daily-then-monthly ranking logic, if you’re building your own scoring instead of trusting theirs.
Watching a specific competitor’s launch
The same endpoint, called on launch day itself, tracks a competitor’s rank movement through the day rather than requiring you to keep the tab open:
async function trackLaunchDay(competitorProductSlug, date) {
const entries = await getDailyLeaderboard(date);
// productSlug is the stable product identifier — match on it rather than
// launch.slug, which names one specific launch event and would miss a
// re-launch.
const match = entries.find((e) => e.launch?.productSlug === competitorProductSlug);
return match ? { rank: match.rank, upvotes: match.launch.upvotes, comments: match.launch.commentsCount } : null;
}
// Poll every 30 minutes on launch day and log rank + upvotes over time
setInterval(async () => {
const status = await trackLaunchDay('some-competitor-product', new Date().toISOString().slice(0, 10));
console.log(new Date().toISOString(), status);
}, 30 * 60 * 1000);
Logging rank and upvotes at 30-minute intervals through launch day gives you a momentum curve — whether a competitor’s launch is accelerating or has stalled — which is a more useful signal than the single end-of-day rank you’d get from checking once.
Practical notes
topicson each launch is worth grouping by if you’re tracking a specific category rather than the whole board —topic-productsfetches a topic’s own listing directly and skips filtering a full leaderboard client-side.- Weekly boards’
dateaccepts any day inside the week you want — you don’t need to calculate the week’s actual start date; pass any date within it, or useyear/weekdirectly. - A launch’s
ranksfield (plural) insidelaunchreflects its position across more than one period at once — a launch can be checked against its daily rank and its monthly rank from the same response, useful for distinguishing “did well for a day” from “held up over the month.”
Next Steps
- Product Hunt API — full endpoint reference and pricing
- Get a free API key — no credit card required