DIY Wi-Fi YouTube subscriber display: ESP8266 + LED Matrix

How to make a live YouTube sub counter with MicroPython. Beginner-friendly, no soldering needed.

Published: Sun, July 6, 2025, 13:00
Updated: Sun, July 6, 2025, 18:45
Category:
Hardware
Tags:
Guide
DIY
Internet of Things

Background πŸ”—

When a family member wanted a live YouTube sub counter for his desk, I saw an opportunity; a chance to teach, to learn, and to encourage making things β€” not just consuming. I haven't done much hardware before, so this was the perfect project for me.

Requirements πŸ”—

I started out with a list of requirements for the hardware and the project.

  • Low-cost
  • Low energy
  • Connect to the Internet via Wi-Fi
  • No soldering
  • Programmable with Python

Hardware shopping list πŸ”—

I wanted something that I could get my hands on quickly (i.e. not sent from abroad, and in stock). I ended up using the ESP8266 microcontroller.

Step 1: Flashing to support MicroPython πŸ”—

The Joy-it NodeMCU ESP8266 comes with Lua support, but I didn't want to learn a new programming language for this project. Instead, I decided to flash the board to run MicroPython - which calls itself "Python for microcontrollers".

I used esptool to flash the ESP8266 microcontroller. Then I found the download link for the ESP8266 firmware to support MicroPython.

# Optional: Setting up virtual environment for Python
python3 -m venv micropython-env
source micropython-env/bin/activate


# Installing esptool
pip install esptool


# Finding the address for the plugged-in microcontroller
ls /dev/tty.*

/dev/tty.Bluetooth-Incoming-Port /dev/tty.usbserial-0001


# Downloading the MicroPython ESP8266 firmware
wget https://micropython.org/resources/firmware/ESP8266_GENERIC-20250415-v1.25.0.bin


# Erasing and flashing the microcontroller
esptool.py --port /dev/tty.usbserial-0001 erase_flash
esptool.py --port /dev/tty.usbserial-0001 --baud 460800 write_flash --flash_size=detect 0 ESP8266_GENERIC-20250415-v1.25.0.bin

esptool.py v4.8.1
Serial port /dev/tty.usbserial-0001
Connecting....
Detecting chip type... ESP8266
Chip is ESP8266EX
Features: WiFi
Crystal is 26MHz
[...output cut for readability...]
Leaving...
Hard resetting via RTS pin...

I now had the board up and running MicroPython.

Step 2: Installing Python IDE and testing the microcontroller πŸ”—

I downloaded and installed Thonny - an excellent, very simple IDE for programming Python and running the code on the board.

Thonny Python IDE

Before connecting the LED matrix I just tested out that my setup worked at all so far by running the following program blinking the on-board LED light.

from machine import Pin
import time

led = Pin(2, Pin.OUT)

for _ in range(5):
    led.off()
    time.sleep(1)
    led.on()
    time.sleep(1)

Step 3: Connecting the LED matrix πŸ”—

Connecting the LED matrix was pretty straightforward. Instead of hunting down the documentation, I got the connection setup from my friend, GPT.

MAX7219 pin NodeMCU ESP8266 pin Comment
VCC 3V3 Power
GND GND Ground
DIN D7 Data In (SPI MOSI)
CS D6 Chip Select (SPI CS)
CLK D5 Clock (SPI SCK)

Step 4: Displaying text πŸ”—

To easily display on the LED matrix I used the script from https://github.com/mcauser/micropython-max7219.

With the script saved to the microcontroller as max7219.py I used the following script to print out TEST on the LED matrix.

import max7219
from machine import Pin, SPI
import time

spi = SPI(1, baudrate=10000000, polarity=0, phase=0)
cs = Pin(12, Pin.OUT)   # D6 (GPIO12)
display = max7219.Matrix8x8(spi, cs, 4)

display.brightness(1)
display.fill(0)
display.show()
time.sleep(2)
display.text('TEST', 0, 0, 1)
display.show()

Step 5: Get YouTube API key and channel ID πŸ”—

To fetch the subscriber count you can set up YouTube Data API v3.

With the API key in hand you just need the channel ID. The ID is not the same as the channel name. You can go to a YouTube channel (e.g., my channel URL would be https://www.youtube.com/roysolberg) and search the source code for youtube.com/channel/ (my ID would then be UCC9FCNnwLWtfV0W5pqhfsoQ).

The URL https://www.googleapis.com/youtube/v3/channels?part=statistics&id=YOUTUBE_CHANNEL_ID&key=YOUTUBE_API_KEY can be used to fetch the subscriber count in JSON format.

Step 6: Connecting all the dots πŸ”—

With all the pieces in hand, it's time to write a script that does the following:

  • Initializes the LED matrix display
  • Connects to Wi-Fi
  • Gets subscriber count from YouTube
  • Displays the text on the LED matrix
  • Proper error handling for all steps
Full script πŸ”—

You can also find the script on GitHub in main.py at https://github.com/roys/python-micro-youtubecounter.

Here's what the full script looks like:

import max7219
from machine import Pin, SPI
import time
import urequests
import network

WIFI_SSID = "FILL_IN_YOUR_WIFI_NETWORK_NAME"
WIFI_PASSWORD = "FILL_IN_YOUR_WIFI_PASSWORD"
YOUTUBE_API_KEY = "FILL_IN_YOUR_YOUTUBE_API_KEY"
YOUTUBE_CHANNEL_ID = "FILL_IN_YOUR_YOUTUBE_CHANNEL_ID"

MAX7219_NUM_OF_MODULES = 4
MAX7219_PIXELS_PER_MODULE = 8
MAX7219_TOTAL_WIDTH = MAX7219_NUM_OF_MODULES * MAX7219_PIXELS_PER_MODULE

display = None


def init_display():
    global display
    spi = SPI(1, baudrate=10000000, polarity=0, phase=0)
    cs = Pin(12, Pin.OUT)  # D6 of NodeMCU
    display = max7219.Matrix8x8(spi, cs, MAX7219_NUM_OF_MODULES)

    display.brightness(3)  # 0-15
    display.fill(0)  # Clear the display
    display.show()


def scroll_text(text, delay=0.05, scroll_off_screen=False):
    if scroll_off_screen:
        text += "    "
    width = len(text) * 8
    for pos in range(-MAX7219_TOTAL_WIDTH, width):
        display.fill(0)
        display.text(text, MAX7219_TOTAL_WIDTH - pos, 0, 1)
        display.show()
        time.sleep(delay)


def display_text(text):
    display.fill(0)
    display.text(text, 0, 0, 1)
    display.show()


def connect_wifi():
    try:
        access_point = network.WLAN(network.AP_IF)
        access_point.active(False)  # No need for an access point
        wlan = network.WLAN(network.STA_IF)
        # wlan.config(pm=network.WLAN.PM_POWERSAVE) # Makes the whole device go sluggish
        wlan.active(True)
        wlan.connect(WIFI_SSID, WIFI_PASSWORD)
        scroll_text(WIFI_SSID, delay=0.03, scroll_off_screen=True)
        for _ in range(50):
            if wlan.isconnected():
                break
            time.sleep(0.1)

        if wlan.isconnected():
            ip = wlan.ifconfig()[0]
            scroll_text(ip)
        else:
            scroll_text(f"Could not connect to Wi-Fi. Restart.")
    except Exception as e:
        scroll_text(f"Error: {str(e)}.")


def print_sub_count():
    url = (
        "https://www.googleapis.com/youtube/v3/channels"
        "?part=statistics"
        f"&id={YOUTUBE_CHANNEL_ID}"
        f"&key={YOUTUBE_API_KEY}"
    )
    last_sub_count = None
    error_count = 0
    while True:
        try:
            status = None
            response = urequests.get(url)
            data = response.json()
            status = response.status_code
            # print(status)
            # print(data)
            # print(url)
            response.close()
            count = str(int(data["items"][0]["statistics"]["subscriberCount"]))
            error_count = 0
            if count != last_sub_count:
                last_sub_count = count
                while len(count) < 4:
                    count = " " + count
                scroll_text(count)
            time.sleep(60)
        except Exception as e:
            error_count += 1
            if error_count >= 10:
                scroll_text(f"Error: {status} - {str(e)}.")
                print(e)
                last_sub_count = None
            time.sleep(60)


init_display()
scroll_text("Starting...", scroll_off_screen=True)
connect_wifi()
print_sub_count()

LED matrix showing YouTube subscriber count
The script running on the ESP8266 microcontroller - showing the YouTube sub count.

Step 7: Making it nice πŸ”—

For now, we decided to use a simple picture frame I had lying around. The parts are so small that they are easy to attach with some tape. I think the end result looks really cool.

Picture frame with YouTube subscriber count

Possible future improvements πŸ”—

The script has been running just perfectly for weeks now, but there are of course always some improvements that could be made. For example:

  • Support subscriber counts over 9,999
  • Retry any Wi-Fi connection problems
  • Better error handling of non-OK HTTP responses

Comments πŸ”—

Reply on Bluesky to join the conversation.

Loading comments…
Get notified when there are new posts! :-)