When the PyPortal is turned on or reset, the following events occur:

  • Display the title page and wait until user taps screen.
  • If user taps screen, display "loading..." while question data is being pulled from API.
  • Display question, answer choices then timer length.
  • Which ever player hits their button first, will get their name displayed on the screen.
  • They then get 5 seconds to answer and hit their button again.
  • Display correct answer and prompt user to tap screen for next question.
  • If no player hits their button within the 10 seconds after the question is displayed, "Time's Up!" appears on the screen.
  • Tap any button to reveal the answer.

How it works

Trivia Time is doing a couple of nifty things to deliver your quiz-off experience!


First, the program displays a bitmap graphic as the screen's background. After the screen is tapped, the second bitmap graphic displays as the background for displaying the trivia questions. These are are 320 x 240 pixel RGB 16-bit raster graphics in .bmp format.

If you would like to create your own background, awesome! You'll want to save the file with these specifications:

  • 320 x 240 pixels
  • 16-bit RGB color
  • Save file as .bmp format

You can then copy the .bmp file to the root level of the CIRCUITPY drive. Make sure you refer to this new filename in the pyportal constructor line:

default_bg=cwd+ "/trivia_title.bmp"

Change that line to use the new filename name, such as:



First we see "loading" appear on the screen along with the source at the bottom (part of the bitmap).

Next the question, answers and timer appear on the screen.

The fonts used here are bitmap fonts made from the Arial Italic typeface. You can learn more about converting type in this guide.


The neat part is that the text is not coming from a file on the device, but rather it is taken from a website!

The Open Trivia Database API

The Open Trivia Database API is where we'll be grabbing our trivia questions from. The API has over 3,000 verified, user-contributed questions to use!

You can choose a number of presets to filter the type of questions you get such as number, category, difficulty, type and encoding.

  • Change the number of questions to 1 then click the "Generate API URL" button.
  • A link will appear on the top of the screen. Copy and paste that link into a new web browser window (or just click here).
{"response_code":0,"results":[{"category":"Entertainment: Japanese Anime & Manga","type":"multiple","difficulty":"medium","question":"In "Highschool DxD", what is the name of the item some humans are born with?","correct_answer":"Sacred Gear","incorrect_answers":["Imperial Arm","Hallowed Relic","Blessed Artifact"]}]}

You may see a large mess of numbers, letters and symbols. This is JSON data!

Head here to beautify the code so we can actually read it!

"Beautified" code:

  "response_code": 0,
  "results": [
      "category": "Entertainment: Japanese Anime & Manga",
      "type": "multiple",
      "difficulty": "medium",
      "question": "In "Highschool DxD", what is the name of the item some humans are born with?",
      "correct_answer": "Sacred Gear",
      "incorrect_answers": [
        "Imperial Arm",
        "Hallowed Relic",
        "Blessed Artifact"

If we look through the JSON file, we'll see a key called question, and 2 others called correct_answer and incorrect_answersincorrect_answers has a sub-tree below it hierarchically with 3 elements.

The raw JSON for these key : value pairs look like this:

"question": "In "Highschool DxD", what is the name of the item some humans are born with?"
"correct_answer": "Sacred Gear"
"incorrect_answers": [
        "Imperial Arm",
        "Hallowed Relic",
        "Blessed Artifact"

Our CircuitPython code is able to grab and parse this data using these variables:

Q_LOCATION = ['results', 0, 'question']
CA_LOCATION = ['results', 0, 'correct_answer']
WA_LOCATION1 = ['results', 0, 'incorrect_answers', 0]
WA_LOCATION2 = ['results', 0, 'incorrect_answers', 1]
WA_LOCATION3 = ['results', 0, 'incorrect_answers', 2]

PyPortal Constructor

When we set up the pyportal constructor, we are providing it with these things:

  • url to query
  • json_path to traverse and find the key:value pair we need
  • status_neopixel pin
  • default_bg path and name to display the background bitmap


With the pyportal set up, we can then use pyportal.fetch() to do the query and parsing the pieces of Open Trivia data. You may notice some responses output data like ". This is HTML code. " Next we'll "clean" the text before it gets displayed.

"Cleaning" JSON with HTML code

In order to "clean" the JSON data (i.e. take HTML codes like " and make them ") we have to take in the JSON data, clean it, and then display it using the Adafruit_Display_Text library. After taking in the data from the API, we use the unescape() function to replace HTML code with desire text.

def unescape(s):
    s = s.replace(""", "''")
    s = s.replace("'", "'")
    s = s.replace("&", "&")
    return s

Main loop

while True:

In the repeating main loop, the following actions are performed:

  1. Check to see if the screen was touched
  2. If screen was touched, clear all text elements on the screen.
  3. Next change the background, then load and display the question.
  4. Call the faceOff() function to start the timer for 10 seconds and wait for the first player to tap their button.
  5. Call faceOff() again to give 5 seconds for player to answer. Then display the answer.
  6. Prompt user to touch screen to display next question.

This guide was first published on Jul 17, 2019. It was last updated on Apr 21, 2024.

This page (Using the App) was last updated on Apr 09, 2024.

Text editor powered by tinymce.