Hacker News Scraper: Stories, Comments, Who's Hiring avatar

Hacker News Scraper: Stories, Comments, Who's Hiring

Pricing

Pay per event

Go to Apify Store
Hacker News Scraper: Stories, Comments, Who's Hiring

Hacker News Scraper: Stories, Comments, Who's Hiring

Hacker News scraper for story, comment and hiring-post research. Select a mode to export stories, comments, search results or parsed hiring-post rows as JSON.

Pricing

Pay per event

Rating

0.0

(0)

Developer

Grit

Grit

Maintained by Community

Actor stats

0

Bookmarked

2

Total users

1

Monthly active users

13 days ago

Last modified

Categories

Share

Hacker News scraper returns public story, comment, search, or parsed hiring-post rows, depending on the selected mode.

Hacker News scraper uses the public source named below and writes its results to the Actor dataset.

What you can do

ModeWhat it returnsSource
topstories, newstories, beststories, askstories, showstories, jobstoriesThe current list, in HN rank order (rank field)Official Firebase API
searchStories, comments, polls, Ask/Show HN matching a query, with date range, minimum points, minimum comments, type and author filters; relevance or newest-firstAlgolia HN Search
commentsThe whole comment tree of each story id or link you give, flattened to rows with depth, parent_id, reply_countAlgolia items endpoint (one request per tree)
whoishiringOne parsed row per job post in the latest (or any named) monthly thread, with the raw text kept next to the parsed fieldsAlgolia items endpoint

Output fields

Fields vary by result type and optional enrichment. The examples below are from sample_output.json.

Output fieldTypeExample value or excerpt from saved sample
kindstring"item"
idinteger49962012
typestring"story"
titlestring or null"Denmark Data Breach Exposes 8.8M People's Personal Data"
urlstring or null"https://www.cpr.dk/cpr-nyt/nyhedsarkiv/2026/okt/omfattende-uautoriseret-adgang-til-borgeres-cpr-oplysninger"
domainstring or null"cpr.dk"
textstring or null"oh, and a mac port is coming :)"
authorstring"clan"
pointsinteger or null198
num_commentsinteger or null139
created_atstring"2026-10-05T08:09:36Z"
created_at_iinteger1791187776
parent_idinteger or null8863
story_idinteger49962012
story_titlestring or null"My YC app: Dropbox - Throw away your USB drive"
depthinteger or null0
reply_countinteger or null32
rankinteger or null1
hn_urlstring"https://news.ycombinator.com/item?id=49962012"
errornullnull
companystring"PrairieLearn (Remote US"
rolestring or null"Full-Stack Software Engineer"
locationstring or null"San Francisco, CA & New York City, NY"
remotebooleantrue
work_modestring"remote"
salary_textstring or null"$100k-$180k"
visastring or null"(We’re not able to sponsor visas at this time.)"
visa_sponsorshipboolean or nullfalse
employment_typearray or null["contract"]
apply_emailstring or null"eric+hn@sidekicklabs.com"
all_urlsarray["https://www.prairielearn.com"]
headerstring"PrairieLearn (Remote US) — Full-Stack Software Engineer — TypeScript / Postgres / React / AI"
header_structuredbooleanfalse
unclassified_segmentsarray or null["TypeScript / Postgres / React / AI"]
raw_textstring"PrairieLearn (Remote US) — Full-Stack Software Engineer — TypeScript / Postgres / React / AI\nPrair…
posted_atstring"2026-10-01T15:02:37Z"
thread_idinteger49922569
thread_titlestring"Ask HN: Who is hiring? (October 2026)"

Story, comment and search rows (kind: "item", event item):

FieldMeaning
id, type, hn_urlItem id, story / comment / poll / job, link to the HN page
title, url, domainStory title, external link and its domain
textPlain text of a comment, Ask HN or job body (text_html too if includeHtml)
author, points, num_commentsAs shown on HN
created_at, created_at_iUTC ISO time and Unix seconds
parent_id, story_id, story_titleWhere a comment sits
depth, reply_countComment trees: 0 = top-level comment; null on the story row
rankPosition in a list mode
errorSet only on error rows, which are never charged

Who-is-hiring rows (kind: "job", event job):

FieldMeaning
company, roleFrom the post header (Company | Role | Location | ...)
location, remote, work_modework_mode is remote, hybrid, onsite or remote_or_onsite when the header says so
salary_textThe salary as written, for example $180k-$250k or 100k-160k GBP
visa, visa_sponsorshipThe sentence(s) that mention visa / sponsorship / relocation; true / false / null when unclear
employment_typefull-time, part-time, intern, contract when named in the header
url, all_urls, apply_emailFirst non-HN link, other links, and the e-mail the post publishes for applying
header, header_structured, unclassified_segmentsThe first line, whether it had the usual pipe layout, header parts the parser could not place
raw_textFull post text, always kept
author, posted_at, hn_url, thread_id, thread_titleSource of the post

The parsing is heuristic: HN does not force a format, so some fields can be empty or wrong. On the October 2026 thread (194 job posts returned) the fields were filled like this: company 100%, location 88%, URL 86%, role 72%, work mode 95%, salary 38%, visa mention 7%, apply e-mail 27%. Always check raw_text when a field matters. Off-topic top-level comments (replies, meta) are skipped and not charged.

Input example

{
"mode": "search",
"query": "sqlite",
"type": "story",
"searchSort": "date",
"dateFrom": "2026-01-01",
"minPoints": 100,
"maxItems": 200
}

Who is hiring, remote Rust jobs from two months:

{ "mode": "whoishiring", "hiringMonths": ["latest", "2026-09"], "hiringRemoteOnly": true, "hiringKeywords": ["rust"] }

Full comment tree of a story:

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

Output example

{
"kind": "job",
"id": 49922693,
"company": "Planlab.ai",
"role": "Product Engineer (Design) & Platform Engineer",
"location": "ONSITE in London, UK",
"remote": false,
"work_mode": "onsite",
"salary_text": "100k-160k GBP",
"visa_sponsorship": true,
"url": "https://planlab.ai/jobs",
"posted_at": "2026-10-01T15:08:44Z",
"hn_url": "https://news.ycombinator.com/item?id=49922693"
}

A real 20-row sample (5 front-page stories, 4 comment rows, 3 search hits, 8 hiring posts) is in sample_output.json.

Pricing (pay per event)

EventPrice
item (story, comment or search row)0.00025 USD
job (parsed Who-is-hiring post)0.002 USD

No start fee. Error rows are free. Set maxItems and the run's maximum cost to cap spend. See PRICING.md for the comparison with other Hacker News actors.

Measured speed (local run, public APIs)

  • Front page, 30 rows: 2.2 s; 100 rows: 2.8 s.
  • Search, 1,200 newest-first stories across two Algolia windows: 4.2 s, no duplicates.
  • Comment tree: 72 rows (the 2007 Dropbox thread, matches HN's own count) in 2.3 s; a 136-row tree in 1.9 s.
  • Who is hiring, latest thread (October 2026): 194 job rows in 1.7 s.

Limits

  • Algolia returns at most 1,000 hits per query. With searchSort: "date" the actor keeps going by moving the date window; relevance search stops at 1,000 and logs a warning.
  • Hacker News data is what is public on the site; dead and deleted items are skipped.
  • minPoints / minComments apply to search and list modes; they do not apply to comment trees or hiring posts.
  • Comment trees of very large threads (thousands of comments) are one big response; keep memory at 512 MB or more for those.
  • Requests are retried with exponential backoff. If an item still fails you get an error row instead of a crashed run.

FAQ

What limits the output? maxItems bounds saved rows. Comment depth and hiring month inputs further narrow the selected mode.

Do I need a proxy, login, or API key? No. It reads the public Hacker News Firebase and Algolia search APIs.

How is it priced? The proposed pay-per-event model charges item for story, comment, or search-hit rows and job for parsed hiring rows. Error rows have no custom event charge.

How are rate limits handled? The API client retries temporary failures with backoff. Source throttling or unavailable items can leave fewer rows than the requested cap.

How fresh are posts? The actor fetches public API data during each run. created_at or posted_at is the source posting time, not a guarantee that a listing remains open.

Why is a hiring field empty? Hiring headers vary; inspect raw_text before relying on parsed job fields.

Use with AI agents / MCP

Every mode is one JSON input and a flat JSON dataset, so an agent can call it as a tool: through the Apify MCP server (mcp.apify.com) add this actor, then ask for "the latest Who is hiring posts that mention Rust and are remote" or "all comments on this HN story". The input schema documents each field, and hiringKeywords, hiringRemoteOnly and maxItems keep the result small enough for a model context.