Social — entry 012 of 39

HackerNews

Verified Jul 2026

The official Hacker News API is a read-only Firebase-backed REST feed publishing items (stories, comments, jobs, polls) and user profiles as simple JSON, with helper endpoints for the current top/new/best/ask/show/job story ID lists. It requires no API key or registration, updates roughly every 30 seconds to reflect live site activity, and has stayed structurally unchanged since Y Combinator open-sourced it in 2015.

The official Hacker News API is a read-only Firebase Realtime Database exposed over plain HTTPS: there is no query language, only a key-value graph you traverse id by id -- an item's `kids` array names its child comment ids, which you fetch one `/item/{id}.json` at a time. A live GET this run against `/item/8863.json` returned genuine JSON for one of the site's oldest stories with no credentials of any kind.

newstechfirebasecommunityread-only
AuthenticationNone requiredCall it straight away — no key, no signup.
HTTPSSupportedTraffic is encrypted in transit.
CORSEnabledCallable directly from browser JavaScript.
PricingFreeNo paid tier — free for the documented use case.
FormatsJSONResponses can be requested as JSON.

GreatAPIs Score

Score74out of 100
Authentication25/25No authentication required
Pricing20/20Free to use
Docs0/20No docs or spec available
Formats9/15Single response format
Freshness20/20Verified within 6 months

Embed this badge

Scored 74 on greatapis.com
<a href="https://greatapis.com/api/hackernews/"><img src="https://greatapis.com/badge/hackernews.svg" alt="Scored 74 on greatapis.com"></a>

Auth quickstart

  1. No API key, signup, or credit card required. A live GET this run against `/item/8863.json` returned genuine JSON while carrying `access-control-allow-origin: *` (no `Origin` header sent), confirming both keyless auth and open CORS with nothing to configure first.
Stored keyNo key stored

Your key is stored only in this browser (localStorage) and sent directly to the API — never to greatapis.

Fetch a story item by id

GEThttps://hacker-news.firebaseio.com/v0/item/8863.json

200 application/json; charset=utf-8

{"by":"dhouston","descendants":71,"id":8863,"kids":[9224,8917,8884,8887,8952,8869,8873,8958,8940,8908,9005,9671,9067,9055,8865,8881,8872,8955,10403,8903,8928,9125,8998,8901,8902,8907,8894,8870,8878,8980,8934,8943,8876],"score":104,"time":1175714200,"title":"My YC app: Dropbox - Throw away your USB drive","type":"story","url":"http://www.getdropbox.com/u/2/screencast.html"}

This is Y Combinator's own 2007 "My YC app: Dropbox" launch post -- one of the site's oldest and most-cited items, so `"by":"dhouston"` and `"id":8863` are durable fixed points to pin; `score` and `descendants` are the fields most likely to have ticked since. There is no batch endpoint: rendering the comment tree means walking `kids` id by id, one request each.

Try it

Developer reference

Base URLhttps://hacker-news.firebaseio.com/v0
Key endpoints
  • GET/item/{id}.json
  • GET/topstories.json
  • GET/user/{id}.json

Gotchas & limits

  • Dropping the trailing `.json` does not 404 -- a live GET this run against `/item/8863` (no suffix) returned HTTP 301 with `Location: https://console.firebase.google.com/project/firebase-hacker-news/database/hacker-news/data/v0/item/8863`, i.e. it redirects to the Firebase *console UI* meant for a logged-in developer, not to any usable API response. Always keep the `.json` suffix.
  • A nonexistent id is **HTTP 200 with the literal body `null`**, not a 404 -- a live GET this run against `/item/999999999.json` returned `200 application/json; charset=utf-8` with body `null`. Treat a bare `null` response as "does not exist", not as an error to catch.
  • `/topstories.json` returns a bare JSON array of **500** story ids and nothing else -- a live GET this run confirmed the count. There is no batch/expand endpoint, so rendering a front page is 1 (the id list) + N (one `/item/{id}.json` per story) requests by design.
  • CORS is Origin-reflecting once a request actually sends one, not a bare wildcard -- a live GET this run with `Origin: https://example.com` against `/item/8863.json` returned `access-control-allow-origin: https://example.com` (echoing the exact request origin) plus `Cache-Control: no-cache`, while the same request with no `Origin` header returned `access-control-allow-origin: *` instead.
  • `?print=pretty` is a real Firebase query param that pretty-prints the JSON response body -- handy when browsing an item by hand in a browser tab, not needed by any client that parses the body programmatically.