Hacker News

How to scrape Hacker News data with an API (2026)

DIY public HN APIs vs a managed Hacker News data API for search, stories, comments, and hiring — tradeoffs and runnable code.

Social FetchUpdated

How to scrape Hacker News data with an API (2026)

DIY public HN APIs vs a managed Hacker News data API for search, stories, comments, and hiring — tradeoffs and runnable code.

Hacker News concentrates technical reality in a way product teams keep rediscovering: a Show HN can make a project, Ask HN threads are candid tooling research, and Who is Hiring is still where a surprising amount of recruiting signal lives. Getting that into a product means choosing between assembling HN's public read surfaces yourself, scraping HTML for the gaps, or calling a Hacker News data API that returns assembled JSON under one key.

This guide compares those paths with real job scenarios — mention watches, digests, comment pulls, hiring parses — and shows runnable Social Fetch examples for search, stories, and users.

The shortest path is a search:

Request
curl -sS \
  -H "x-api-key: $SOCIALFETCH_API_KEY" \
  -G "https://api.socialfetch.dev/v1/hackernews/search" \
  --data-urlencode "query=Dropbox"

You'll need an API key and curl or the TypeScript SDK. New to the API? Start with the Quickstart.

The three ways to get Hacker News data

ApproachBest whenThe real cost
DIY public APIsHN-only scripts; you want to own every hopFeed id fan-out, comment walks, search/schema glue, HTML favorites
DIY HTML / browserOne-off research or fields not in public JSONMarkup drift, proxies, session babysitting
Data API (Social Fetch)Search, stories, users, hiring in product code now — ideally beside Reddit or WebMetered per completed lookup; provider keeps routes working

For most production apps that need HN on demand beside other networks, the data API is the fastest route to reliable JSON — one REST surface with the same data + meta envelope as Reddit or Instagram. DIY public APIs are genuinely worth it when HN is the only network and a staff engineer already owns the quirks.

Why DIY HN clients turn into a maintenance project

Public HN read APIs are more stable than Instagram GraphQL. The maintenance tax is the assembly:

  • Feeds return ids. Digests need titles, scores, URLs, and comment counts — so every cron tick fans out item lookups.
  • Comments are trees. Busy Show HN threads need paging strategy, not a single recursive dump that times out.
  • Search ≠ story schema. Keyword monitors map hit fields into the same model you use for story gets, or you maintain two parsers.
  • Favorites and hiring. Public favorites live on HTML pages. Who is Hiring is a monthly comment thread you discover and structure yourself.

For a personal script that's fine. For a customer-facing monitor, you've signed up to own glue code forever. Broader build-vs-buy: Social Fetch vs DIY scraping.

Why "just call the public APIs" is incomplete for products

HN's public surfaces are the right answer when you want first-party public JSON and can wire multiple clients. They leave gaps that product tickets keep rediscovering:

  • Hydrated front-page / show / ask / jobs digests without id fan-out.
  • One envelope for search hits and story cards.
  • Cursor-friendly comment pages for long threads.
  • Public favorites with a typed outcome when the list is private.
  • Structured Who is Hiring rows instead of one blob of top-level comments.

So if you need one key and one error shape across networks, DIY leaves a glue gap by design. Reach for public APIs when HN is standalone infrastructure; reach for a data API when HN is one enrichment source beside Reddit or Web.

Using the Social Fetch API

Social Fetch exposes Hacker News under documented /v1/hackernews/** routes — search, feeds, stories, comments, items, users, favorites, Who is Hiring, and thin update helpers. One header authenticates every call.

Request
TypeScript
const = await client.tiktok.({
handle: "charlidamelio",
});
if (result.ok) {
const { profile } = result.value.data;
}
Response
JSON
{
"data": {
"lookupStatus": ,
"profile": {
"handle": "charlidamelio",
"displayName": "Charli D'Amelio",
},
"metrics": {
"followers": 155200000
}
},
"meta": {
"creditsCharged":
}
}

Hover underlined tokens for details.

Search mentions

Brand and launch monitors start here — query the product name, optionally narrow with author, domain, or minPoints, then hydrate only the ids you keep:

Request
const params = new URLSearchParams({"query":"Dropbox"});

const response = await fetch(
  `https://api.socialfetch.dev/v1/hackernews/search?${params.toString()}`,
  {
    headers: {
      "x-api-key": process.env.SOCIALFETCH_API_KEY,
    },
  }
);

const body = await response.json();

console.log(response.status, body);

Docs: Search Hacker News. Credit-metered per completed page — trust meta.creditsCharged. An empty hits array with no further pages is a completed empty result, not a transport failure.

Get a story

Classic Show HN Dropbox (8863) is a good smoke-test id:

Request
const response = await fetch(
  "https://api.socialfetch.dev/v1/hackernews/stories/8863",
  {
    headers: {
      "x-api-key": process.env.SOCIALFETCH_API_KEY,
    },
  }
);

const body = await response.json();

console.log(response.status, body);

Branch on data.lookupStatus (found, not_found, not_story). Comment trees are a separate paginated route: story comments.

Get a user

Author analysis starts with the user card, then siblings for submissions, comments, or public favorites:

Request
const response = await fetch(
  "https://api.socialfetch.dev/v1/hackernews/users/pg",
  {
    headers: {
      "x-api-key": process.env.SOCIALFETCH_API_KEY,
    },
  }
);

const body = await response.json();

console.log(response.status, body);

Reading the response

Search returns hits plus page metadata:

Response
json
{
  "data": {
    "query": "Dropbox",
    "hits": [
      {
        "id": 8863,
        "type": "story",
        "author": "dhouston",
        "title": "My YC app: Dropbox - Throw away your USB drive",
        "score": 104,
        "itemUrl": "https://news.ycombinator.com/item?id=8863"
      }
    ],
    "page": {
      "page": 0,
      "pageSize": 20,
      "returned": 1,
      "hasMore": false,
      "nextPage": null
    }
  },
  "meta": {
    "requestId": "req_01example",
    "creditsCharged": 1,
    "version": "v1"
  }
}

Story gets return a typed card:

Response
json
{
  "data": {
    "lookupStatus": "found",
    "story": {
      "id": 8863,
      "author": "dhouston",
      "title": "My YC app: Dropbox - Throw away your USB drive",
      "url": "http://www.getdropbox.com/u/2/screencast.html",
      "score": 104,
      "commentCount": 71
    }
  },
  "meta": {
    "requestId": "req_01example",
    "creditsCharged": 1,
    "version": "v1"
  }
}

The one gotcha: HTTP 200 does not always mean "persist this row." Empty search hits are a completed empty result; story/user routes expose lookupStatus for misses and wrong item types. Every response carries meta.requestId. See Errors and Credits.

What you can build

  • Launch and brand monitors — search product names, then pull stories and comments for the hits that matter.
  • Front-page digests — ranked feeds with hydrated items for Slack/email roundups.
  • Hiring intel — structured Who is Hiring rows with best-effort company/role/location fields (plain text remains source of truth).
  • Author analysis — user cards plus submissions, comments, and public favorites.

Vendor shopping: Best Hacker News APIs & scrapers in 2026. Related: Reddit product research.

FAQ

It depends on your jurisdiction, what you collect, and how you use it. HN publishes public read surfaces and public HTML. You remain responsible for Y Combinator's terms and applicable law. This is not legal advice.

Can't I just use Hacker News's public APIs myself?

Yes for HN-only scripts. You still assemble hydration, comment paging, search mapping, and HTML-only surfaces. For multi-platform enrichment, a managed data API is often shorter. See Why "just call the public APIs" is incomplete for products.

How fresh is the data?

Each request fetches live at call time. meta.requestId traces a specific lookup.

What happens if a story or user doesn't exist?

Check data.lookupStatus where present. Don't treat 200 alone as found.

How are credits charged?

Credits charge when a lookup completes, including empty search pages and typed misses. Each HN request or cursor page is credit-metered. Always reconcile against meta.creditsCharged.

How does this compare to other providers?

See Best Hacker News APIs & scrapers in 2026, vs Apify, and the compare hub.


Ready to try it? Get an API key — new accounts include 100 free credits. Platform hub: /platforms/hackernews.