Social — entry 012 of 39
HackerNews
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.
GreatAPIs Score
Auth quickstart
- 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.
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
{"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
https://hacker-news.firebaseio.com/v0- 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.