Hacker News API: Stories, Comments, Search & Who's Hiring Jobs avatar

Hacker News API: Stories, Comments, Search & Who's Hiring Jobs

Pricing

from $2.00 / 1,000 jobs

Go to Apify Store
Hacker News API: Stories, Comments, Search & Who's Hiring Jobs

Hacker News API: Stories, Comments, Search & Who's Hiring Jobs

Hacker News front page, search, full comment threads and structured jobs from the monthly "Who is hiring?" threads (company, role, location, remote, visa, salary). Official Firebase and Algolia APIs, no scraping or proxies. Monitor mode returns only new items.

Pricing

from $2.00 / 1,000 jobs

Rating

0.0

(0)

Developer

Local Wire

Local Wire

Maintained by Community

Actor stats

0

Bookmarked

2

Total users

1

Monthly active users

3 days ago

Last modified

Features

Limited permissions

Share

Get Hacker News data as clean JSON from the official Hacker News APIs: front-page stories for $0.30 per 1,000, comments for $0.10 per 1,000, and structured jobs from the monthly "Ask HN: Who is hiring?" threads for $2 per 1,000, with no start fee. One Actor covers the front page and other lists, full-text search of stories and comments, complete comment threads, and Who is hiring posts parsed into company, role, location, remote, visa and salary fields.

It uses only the official Hacker News API (Firebase) and the HN Search API (Algolia). It does not scrape web pages and needs no proxies or login. Monitor mode returns only items you have not had before, so it suits scheduled alerts.

What you get

Every record has a type: story, comment or job. The dataset has a table view for each.

Who is hiring job

On the first weekday of each month Hacker News opens an "Ask HN: Who is hiring?" thread. Employers post one top-level comment each, usually starting with a line like:

Acme | Senior Backend Engineer | Berlin, Germany | REMOTE (EU) | Full-time | €90k–€120k | https://acme.example/jobs

The Actor reads that line and the rest of the post into fields:

{
"type": "job",
"id": 50300001,
"threadId": 50298765,
"threadTitle": "Ask HN: Who is hiring? (November 2026)",
"threadMonth": "2026-11",
"company": "Acme",
"companyNote": "YC W24",
"roles": ["Senior Backend Engineer"],
"locations": ["Berlin, Germany"],
"remote": true,
"hybrid": false,
"onsite": false,
"remoteScope": "EU",
"employmentTypes": ["full-time"],
"visaSponsorship": true,
"salary": "€90k–€120k",
"salaryMin": 90000,
"salaryMax": 120000,
"salaryCurrency": "EUR",
"salaryPeriod": "year",
"applyUrl": "https://acme.example/jobs",
"urls": ["https://acme.example/jobs"],
"tags": [],
"headline": "Acme (YC W24) | Senior Backend Engineer | Berlin, Germany | REMOTE (EU) | Full-time | €90k–€120k | https://acme.example/jobs",
"description": "Acme builds … (the whole post as plain text)",
"author": "acme_hiring",
"postedAt": "2026-11-02T16:05:23.000Z",
"hnUrl": "https://news.ycombinator.com/item?id=50300001",
"parseQuality": "structured"
}

Parsing is deterministic and has been tested against real monthly threads. In November and October 2026 the company was found for 98-99% of posts, and an office location or remote flag for 93-94%. A field is only filled when the post states it: roles, salary and visa sponsorship appear only when the employer gives them. parseQuality is structured when the post has the usual |-separated first line and freeform when it does not. The full post text is always in description, and the original post is linked in hnUrl.

Story

{
"type": "story",
"id": 50391456,
"storyType": "story",
"title": "Tesla to wind down Cybertruck production",
"url": "https://www.example.com/article",
"domain": "example.com",
"text": null,
"author": "someone",
"points": 619,
"commentCount": 1364,
"createdAt": "2026-11-06T10:12:00.000Z",
"hnUrl": "https://news.ycombinator.com/item?id=50391456",
"list": "top",
"rank": 3,
"source": "firebase",
"fetchedAt": "2026-11-06T20:00:00.000Z"
}

storyType is story, ask, show, launch, job or poll. list and rank are filled in lists mode. source says which API the record came from.

Comment

{
"type": "comment",
"id": 50397540,
"storyId": 50397219,
"storyTitle": "Firecracker VM Escape: PwnEscape Part 2",
"storyUrl": "https://www.example.com/blog/firecracker-escape",
"parentId": 50397219,
"depth": 1,
"author": "someone",
"text": "Plain text, with links written out in full.",
"replyCount": 2,
"createdAt": "2026-11-06T19:40:00.000Z",
"hnUrl": "https://news.ycombinator.com/item?id=50397540",
"source": "algolia",
"fetchedAt": "2026-11-06T20:00:00.000Z"
}

depth is 1 for a direct reply to the story. In search results depth and replyCount are null, because search hits do not carry their position in the thread.

The run's key-value store also gets an OUTPUT record. It counts what was scanned, filtered out, already returned (monitor mode) and returned, and gives each Who is hiring thread's job count.

Quick start

The Actor runs with no input at all: you get the current top 30 front-page stories for less than one cent.

{}

The jobs from the latest Who is hiring thread that mention Python and offer remote work:

{
"mode": "whoIsHiring",
"hiringKeywords": ["python"],
"hiringRemoteOnly": true
}

Stories about SQLite from the last week, most relevant first:

{
"mode": "search",
"query": "sqlite",
"lastDays": 7,
"maxResults": 100
}

Every comment on one story:

{
"mode": "comments",
"storyIds": ["https://news.ycombinator.com/item?id=8863"]
}

Modes

ModeWhat you getTypical input
lists (default)Stories from the top, new, best, Ask HN, Show HN and job lists, with rank{"lists": ["top"], "maxItemsPerList": 30}
searchStories and/or comments matching a query, by relevance or newest first{"mode": "search", "query": "sqlite", "lastDays": 7}
commentsEvery comment in one or more threads, in thread order, with depth and parent{"mode": "comments", "storyIds": ["https://news.ycombinator.com/item?id=8863"]}
whoIsHiringOne structured job record per employer post in "Ask HN: Who is hiring?"{"mode": "whoIsHiring", "hiringRemoteOnly": true}

Input reference

FieldUsed inTypeDefaultWhat it does
modealltextlistslists, search, comments or whoIsHiring.
listslistslist["top"]top, new, best, ask, show, job. A story in several lists is returned once.
maxItemsPerListlistsnumber 1-50030How far down each list to read. The front page is the first 30.
querysearchtextemptyWords to find in titles, URLs, story text and comments. Empty lists everything in the date window.
searchTypessearchlist["story"]story, comment, ask_hn, show_hn, poll, front_page. Several values return any of them.
sortBysearchtextrelevancerelevance or date (newest first). In monitor mode the default is date.
lastDayssearchnumber 1-3650noneOnly items from the last N days. Ignored when dateFrom is set.
dateFrom / dateTosearchdatenoneA date window, e.g. 2026-01-01 to 2026-01-31 (inclusive).
minPointslists, searchnumbernoneOnly stories with at least this many points.
minCommentslists, searchnumbernoneOnly stories with at least this many comments.
storyIdscommentslistrequired in this modeStory ids or links like https://news.ycombinator.com/item?id=8863.
includeStorycommentstrue/falsefalseAlso return the story record before its comments.
maxCommentsPerStorycommentsnumber 1-20,0001000Stop after this many comments for each story.
hiringMonthswhoIsHiringlistlatestWhich monthly threads to read, like 2026-11.
hiringThreadswhoIsHiringnumber 1-241When no months are given, how many of the latest threads to read.
hiringKeywordswhoIsHiringlistnoneOnly posts that mention ANY of these words in the company, roles or text.
hiringLocationswhoIsHiringlistnoneOnly posts that name ANY of these places in their locations, remote region or first line.
hiringRemoteOnlywhoIsHiringtrue/falsefalseOnly posts that offer remote work.
hiringVisaOnlywhoIsHiringtrue/falsefalseOnly posts that say they sponsor visas.
onlyNewalltrue/falsefalseMonitor mode: return, and charge for, only items no earlier run with the same settings returned.
monitorKeyalltextautomaticA name for the monitor's memory. Without one, each set of settings gets its own.
maxResultsallnumber 1-100,0001000Stop after this many records in total.

Invalid input fails at once with a message that lists every problem, so a person or an AI agent can fix it in one go.

Monitor mode: only new items

Set onlyNew: true and schedule the Actor. Each run returns, and charges for, only stories, comments or jobs that no earlier run with the same settings returned. Typical uses:

  • Mentions of your brand: {"mode": "search", "query": "yourproduct", "searchTypes": ["story", "comment"], "onlyNew": true} every hour.
  • New jobs as they are posted: {"mode": "whoIsHiring", "hiringKeywords": ["rust"], "onlyNew": true} every day; employers keep posting all month.
  • Front-page alerts: {"lists": ["top"], "minPoints": 300, "onlyNew": true} every 30 minutes.

The memory lives in a key-value store named hacker-news-monitor in your account. Dates and limits are not part of it, so a rolling lastDays window does not reset a monitor. Give a monitor its own name with monitorKey, or delete the store to start over.

Use cases

  • Job hunting and recruiting research. Turn each month's Who is hiring posts into a filterable table, for example "remote Rust jobs in Europe that sponsor visas".
  • Brand and competitor monitoring. Get an alert when your product, a competitor or a topic is mentioned in a story or a comment.
  • Tech trend tracking. Count stories and comments about a technology by week, or snapshot the front page with points, comment counts and rank.
  • Discussion analysis. Download a whole thread, with each comment's depth and parent, for sentiment analysis, summaries or retrieval.
  • Salary research. Published pay ranges from Who is hiring posts as numbers with currency and period.
  • AI agents. Small, predictable records that an agent can fetch as a tool through Apify's MCP server.

Pricing

You pay per record returned and nothing to start a run:

RecordPricePer 1,000
Story$0.0003$0.30
Comment$0.0001$0.10
Who is hiring job$0.002$2.00

There is no monthly rental. You pay nothing for records that your filters drop or that a monitor has already returned.

What you runRecords returnedCost
The default run: top 30 stories30 stories$0.009
A search that returns 1,000 stories1,000 stories$0.30
A large thread's comments1,000 comments$0.10
A whole Who is hiring threadabout 300 jobsabout $0.60
Remote Python jobs from the latest threadabout 40 jobsabout $0.08
An hourly brand monitor that finds 5 comments and 1 story a dayabout 180 a monthabout $0.02 a month

A monthly Who is hiring thread usually holds 200 to 400 employer posts. To cap spending, set Max cost per run in the run options, or lower maxResults. The Actor stops cleanly at the limit and says so in its status message.

Use it from the API

Run the Actor and get the records back in one request:

curl -X POST "https://api.apify.com/v2/acts/localwire~hacker-news/run-sync-get-dataset-items" \
-H "Authorization: Bearer <YOUR_APIFY_TOKEN>" \
-H "Content-Type: application/json" \
-d '{"mode": "whoIsHiring", "hiringKeywords": ["python"], "hiringRemoteOnly": true}'

That endpoint waits up to five minutes, which is enough for most runs. For a very large search or thread, start the Actor with POST /v2/acts/localwire~hacker-news/runs and read the run's dataset when it has finished.

With the Apify client for JavaScript:

import { ApifyClient } from "apify-client";
const client = new ApifyClient({ token: process.env.APIFY_TOKEN });
const run = await client.actor("localwire/hacker-news").call({
mode: "search",
query: "postgres",
searchTypes: ["story"],
lastDays: 30,
minPoints: 100,
});
const { items } = await client.dataset(run.defaultDatasetId).listItems();

With the Apify client for Python:

from apify_client import ApifyClient
client = ApifyClient("<YOUR_APIFY_TOKEN>")
run = client.actor("localwire/hacker-news").call(run_input={
"mode": "comments",
"storyIds": ["https://news.ycombinator.com/item?id=8863"],
"includeStory": True,
})
records = list(client.dataset(run["defaultDatasetId"]).iterate_items())

Results can be downloaded from the dataset as JSON, CSV, Excel, XML or JSON Lines.

Use it from an AI agent (MCP)

Apify's hosted MCP server is at https://mcp.apify.com. Add it to any MCP client that supports remote servers and sign in with your Apify account when the browser opens (or send an Authorization: Bearer <APIFY_TOKEN> header).

To give the agent only this Actor as a tool, use this server URL:

https://mcp.apify.com?tools=localwire/hacker-news
{
"mcpServers": {
"apify": {
"url": "https://mcp.apify.com?tools=localwire/hacker-news"
}
}
}

The agent then sees the Actor's input fields with their descriptions and defaults. No field is required: an empty input returns the front page, and mode selects everything else. Questions that work well:

  • "Which companies in this month's Who is hiring thread sponsor visas for ML roles in London?"
  • "What is on the Hacker News front page right now with more than 300 points?"
  • "Summarise what people said about SQLite on Hacker News this week."

Integrations

Runs can be started on a schedule or by another system, and results can be sent on:

  • Make, n8n and Zapier have Apify integrations that run an Actor and pass its dataset to the next step, for example to a spreadsheet, email or a chat channel.
  • Webhooks call your endpoint when a run succeeds or fails.
  • LangChain and other agent frameworks can use Apify Actors as tools.
  • The Apify API and the JavaScript and Python clients cover everything else.

FAQ

Is there an official Hacker News API?

Yes, two. The Hacker News API on Firebase serves the live lists and single items, and the HN Search API by Algolia serves full-text search, date ranges and whole threads. Both are free and need no key. This Actor uses both and adds what they do not do themselves: one record format, paging past the search limit, structured Who is hiring jobs, monitor mode, scheduling and exports.

How do I get the Hacker News "Who is hiring?" thread as JSON or CSV?

Run the Actor with {"mode": "whoIsHiring"}. Each employer's post becomes one record with company, roles, locations, remote, visa and salary fields, and you can download the dataset as JSON, CSV or Excel. Add hiringMonths for earlier months.

How do I search Hacker News by keyword and date?

Use mode: "search" with a query and either lastDays or dateFrom and dateTo. Set searchTypes to ["story"], ["comment"] or both, and sortBy to date for newest first.

How do I download all comments from a Hacker News thread?

Use mode: "comments" and put the story's id or link in storyIds. Every comment comes back once, in thread order, with its depth and parentId, so you can rebuild the tree.

How do I monitor Hacker News for mentions of my company?

Search for your name in stories and comments with onlyNew: true, and schedule the run every hour. Each run returns only mentions it has not returned before, and a run that finds nothing new costs nothing.

Can I get more than 1,000 search results?

Yes, with sortBy: "date". The HN Search API serves at most 1,000 results per query, so relevance search stops there. Newest-first search continues by moving the date window back automatically.

Does it return user profiles or karma?

No. Authors appear as their public Hacker News usernames, and user profiles are never fetched.

How much does it cost to get a whole Who is hiring thread?

About $0.40 to $0.80: a thread has roughly 200 to 400 employer posts at $0.002 each.

Does it need proxies or a login?

No. Both APIs are public and official. The Actor identifies itself with its own User-Agent.

Is it affiliated with Hacker News?

No. This Actor is not affiliated with or endorsed by Y Combinator, Hacker News or Algolia.

Limitations

  • Sources. The official Hacker News API for lists and items, and the HN Search API by Algolia for search, date windows and whole threads. Nothing is scraped from web pages.
  • Relevance search returns at most 1,000 results per query. Use newest-first search to go further.
  • Points and comment counts are as of the moment of the run. Search results can be a few minutes behind the live site.
  • Comment points are not public, so comments have none and minPoints applies to stories only.
  • Who is hiring covers the monthly employer threads only. "Who wants to be hired?" and the freelancer threads are not read, because those posts are individuals' personal details. Replies to job posts are not returned, and posts that follow the "Who wants to be hired?" template but were placed in the hiring thread are skipped.
  • Job fields are parsed from free text. Posts that do not follow the usual first-line format are returned with fewer fields filled (parseQuality: "freeform"). Check description when a field matters.
  • If an API is unavailable or rate-limits requests, the Actor waits and retries a few times, honouring Retry-After, then reports the problem in the status message and the OUTPUT record. It does not use proxies or any other way round a limit.

Data, privacy and terms

Authors are their public Hacker News usernames, as the official APIs return them. User profiles are never fetched. Email addresses and phone numbers are removed from all text and replaced with [email removed] and [phone removed], and mailto: links are dropped, so apply through the links in each post (applyUrl and urls).

The Who wants to be hired and freelancer threads are never read.

This Actor is not affiliated with or endorsed by Y Combinator, Hacker News or Algolia. Please respect the Hacker News guidelines when you use the data.

More from this developer

Jobs:

Other data:

Feedback

Spotted a job post that was read wrongly, or want another field? Open an issue on the Actor's Issues tab with the post's link and we will improve the parser.