Web Data LabsBlog › Useless Facts Scraper

How to Get Random Fun Facts Programmatically (Useless Facts API Guide)

May 3, 2026  ·  5 min read

Random trivia is one of those weird primitives that ends up in more software than you would expect. Daily newsletters that open with a curious fact to lift the rest of the email. Trivia apps that need an endless supply of fresh material so the same player does not see the same card twice in a week. Discord and Slack bots that drop a fact-of-the-day at 9am to nudge a quiet channel back to life. Chatbots that fall back to a friendly aside when the user asks something they cannot answer. Educational platforms that intersperse facts between lessons to keep attention. None of these products are about trivia, but every one of them needs a steady supply of short, well-formed, original facts on tap.

This post walks through why programmatic fun-fact data is its own surprisingly fiddly little problem domain, what a clean fact feed actually looks like, and how to pull random facts, fact-of-the-day, or specific facts by ID through our hosted scraper without writing or maintaining any code yourself.

Why programmatic trivia matters

What makes fact data access fiddly

The Useless Facts API is a generous public good, but building production fact features directly on top of any third-party feed has a familiar set of failure modes. The endpoint can be rate-limited, the JSON shape can shift over time, the source domain can move, and the language coverage can change. Beyond plain availability, the consumer side has its own quirks: facts contain quotation marks and special characters that need careful escaping, repeated random calls can return the same fact twice in a row, and the fact-of-the-day endpoint changes once per UTC day — not once per local day — which surprises users in distant timezones.

Random does not mean uniform: A naive integration that fires “give me one random fact” on every page load will, sooner or later, hand the same fact to the same user twice in a session. A production trivia feature wants either a batch-and-shuffle pattern, a per-user seen-set with deduplication, or both. The data layer is one decision; the “do not show this user the same fact twice” layer is a separate one and worth thinking about up front.

What our scraper returns

The actor normalises every fact to the same compact shape, so downstream code does not have to branch on which endpoint produced it:

{
  "id": "5f048654915ace42c3ab2c246fdc2457",
  "text": "US gold coins used to say “In Gold We Trust”.",
  "source": "djtech.net",
  "source_url": "https://www.djtech.net/humor/shorty_useless_facts.htm",
  "language": "en",
  "permalink": "https://uselessfacts.jsph.pl/api/v2/facts/5f048654915ace42c3ab2c246fdc2457",
  "scraped_at": "2026-05-03T12:39:29.238Z"
}

How to call it

Every run takes a small JSON input describing what you want. There are four supported actions:

ActionWhat you getRequired input
randomN random factscount (default 1), language
todayThe fact of the day (changes once per UTC day)language
byIdOne specific fact by IDid, language
batchMultiple specific facts by IDids (array), language

Five random English facts

{
  "action": "random",
  "count": 5,
  "language": "en"
}

Today's fact in German

{
  "action": "today",
  "language": "de"
}

One specific fact by ID

{
  "action": "byId",
  "id": "5f048654915ace42c3ab2c246fdc2457",
  "language": "en"
}

A batch of facts by ID (useful for re-fetching a curated set)

{
  "action": "batch",
  "ids": [
    "5f048654915ace42c3ab2c246fdc2457",
    "b2c7f6cd9240e38dd4d574d2697d74ff"
  ],
  "language": "en"
}

Wiring it into a daily newsletter or bot

The natural pattern is a small scheduled job — a cron, a serverless function, or a daily Apify run — that requests one fact (or a small batch), stores it in your own database keyed by date, and renders it from there. You get caching, replay, and editorial override for free, and the third-party API only sees one call per day per surface instead of one call per page view. For chatbots and Discord/Slack integrations, fetching a small batch of 50 facts in the morning and serving them locally over the rest of the day is almost always the right shape: it stays well inside everyone’s rate limits and keeps response time inside the bot loop fast.

If you do roll your own scraper

If you want to build the data plumbing yourself rather than use a managed actor, the part that gets people in trouble is not the first request — it is everything around it. Rate limits, retries on transient failures, IP rotation when a single endpoint pushes back, language-aware caching, deduplication for “random” results, and consistent UTF-8 handling for non-ASCII characters in fact text. For anything where the data layer is incidental to the actual product (a newsletter, a bot, an app), a proxy provider like Oxylabs handles the “do not get blocked” layer, and a managed actor handles the “do not babysit a scraper at 3am” layer.

Try it

The actor lives on Apify and is callable from any language that can make an HTTP request: Python, Node, Go, Bash, Zapier, n8n, or directly from the Apify console. You pay only for facts returned, with no monthly minimum and no credit card needed for the first runs.