How to get free trivia questions from an API
Will Fry4 min read
If you're building a quiz app, a game for your Discord server or something for the next pub quiz, the code is usually the easy bit. Finding enough good questions is a lot harder.
That's what The Trivia API is for. One request gets you a batch of random multiple choice questions as JSON. It's free for non-commercial projects, and you don't need to sign up or get an API key to start.
This post is basically everything you need to get going: making a request, filtering the questions you get back, and using them from JavaScript, TypeScript or Python.
Your first request
Everything starts at /v2/questions. Paste this into a terminal:
curl "https://the-trivia-api.com/v2/questions?limit=1"You get back an array of questions:
[
{
"id": "65056fd57a97013de78b54d1",
"category": "science",
"difficulty": "easy",
"question": { "text": "What best describes the pH of lemon juice?" },
"correctAnswer": "Acidic",
"incorrectAnswers": ["Neutral", "Basic", "Sterile"],
"tags": ["science"],
"type": "text_choice",
"regions": [],
"isNiche": false
}
]Each one has the question text, the correct answer and three incorrect ones. It also has a category, difficulty and tags, which you can filter on (more on that next).
Picking the questions you want
By default you get 10 questions from any category, at any difficulty. Query parameters narrow that down, and you can mix and match them:
| Parameter | What it does | Example |
|---|---|---|
limit | How many questions you get. Defaults to 10. | limit=20 |
categories | Only questions from these categories | categories=science,history |
difficulties | Only easy, medium or hard questions | difficulties=easy,medium |
tags | Only questions about these more specific topics | tags=dinosaurs,space |
Multiple values are comma separated. The categories are music, sport_and_leisure, film_and_tv, arts_and_literature, history, society_and_culture, science, geography, food_and_drink and general_knowledge.
Tags are where it gets more specific. There are over 1,500 of them, from football to the_beatles (the tags endpoint has the full list).
So five hard geography questions looks like this:
curl "https://the-trivia-api.com/v2/questions?limit=5&categories=geography&difficulties=hard"JavaScript
Plain fetch is all you need, and it works in the browser and in Node 18+. URLSearchParams saves you from gluing the query string together yourself:
const params = new URLSearchParams({
limit: "10",
categories: "science,history",
difficulties: "easy",
});
const response = await fetch(`https://the-trivia-api.com/v2/questions?${params}`);
if (!response.ok) {
throw new Error(`The Trivia API responded with ${response.status}`);
}
const questions = await response.json();
for (const question of questions) {
console.log(question.question.text);
}Shuffling the answers
The correct answer comes back separately from the incorrect ones, so you'll want to mix them up before showing them to anyone. A Fisher-Yates shuffle is the way to do it:
const shuffle = (items) => {
const shuffled = [...items];
for (let i = shuffled.length - 1; i > 0; i--) {
const j = Math.floor(Math.random() * (i + 1));
[shuffled[i], shuffled[j]] = [shuffled[j], shuffled[i]];
}
return shuffled;
};
const answers = shuffle([question.correctAnswer, ...question.incorrectAnswers]);You'll probably see answers.sort(() => Math.random() - 0.5) suggested a lot. I'd avoid it: it's biased, so the correct answer turns up in some positions more often than others. Your more competitive players will notice.
TypeScript
If you're using TypeScript, there's an SDK: @trivia-api/sdk. It has typed functions for every endpoint, no dependencies, and it works anywhere fetch does.
npm install @trivia-api/sdkimport { getRandomQuestions } from "@trivia-api/sdk";
const questions = await getRandomQuestions({
limit: 10,
categories: "science,history",
difficulties: "easy",
});
for (const question of questions) {
// The type field tells TypeScript which kind of question this is
if (question.type === "text_choice") {
console.log(question.question.text, question.correctAnswer);
}
}If a request fails it throws an ApiError with the status code on it, so it's easy to tell a rate limit (429) apart from your wifi dropping out.
Python
Same thing with requests:
import requests
response = requests.get(
"https://the-trivia-api.com/v2/questions",
params={"limit": 10, "categories": "science,history", "difficulties": "easy"},
timeout=10,
)
response.raise_for_status()
for question in response.json():
print(question["question"]["text"])
print("Answer:", question["correctAnswer"])Limits (and when you need a key)
Without a key you can get up to 50 questions per request. Ask for more and you'll just get 50. There's also a rate limit of 20 requests every 5 seconds per IP address, and anything over that gets a 429.
In practice that's plenty, as long as you fetch a whole quiz's worth of questions up front rather than one at a time.
If you're using it commercially you'll need a subscription. That also gets you:
- bigger batches
- sessions, so players never see the same question twice
- image questions
- questions in other languages
What next
The docs have every endpoint and parameter, with example responses.
Build with The Trivia API
The docs cover every endpoint, parameter and response. No API key is needed to get started.