DIY YouTube View Counter: Because Refreshing Your Browser is for Amateurs

📺 DIY YouTube View Counter: Because Refreshing Your Browser is for Amateurs



Let's be honest: you just uploaded a video, and now you’re refreshing the page every 3 seconds. Your "F5" key is screaming for mercy. It’s time to outsource that obsession to a NodeMCU and a tiny OLED screen.

In this guide, we’re going to build a desktop gadget that stares at the YouTube API so you don't have to.

🛠 The "Ingredients" (Hardware)

  • NodeMCU (ESP8266): The brains. Cheap, WiFi-enabled, and prone to making you feel like a hacker.

  • 0.96" OLED Display (I2C): 128x64 pixels of pure data-glory.

  • Jumper Wires: For when you want to feel like you’re defusing a bomb.

  • A YouTube API Key: Our golden ticket into Google’s data vault.

🔌 The Wiring (Don't Set Anything on Fire)

The OLED uses the I2C protocol, which is fancy talk for "it only needs two data wires." Connect them like this:

OLED PinNodeMCU PinWhy?
VCC3.3VFeed the screen electricity.
GNDGNDCompleting the circle of life.
SCLD1The "Clock" pin (keeps things in sync).
SDAD2The "Data" pin (sends the juicy numbers).

🔑 Step 1: Steal... I mean, Request an API Key

You can't just knock on Google's door and ask for data. You need a key.

  1. Go to the Google Cloud Console.

  2. Create a project (Call it "View-Counter-3000").

  3. Search for "YouTube Data API v3" and click Enable.

  4. Go to Credentials > Create Credentials > API Key.

  5. Keep it secret. If you post it on GitHub, a bot will find it and use up your quota in 4 seconds.


💻 Step 2: The Code

Copy this into your Arduino IDE. You'll need the Adafruit SSD1306 and ArduinoJson (v6+) libraries installed.


#include <ESP8266WiFi.h>

#include <WiFiClientSecure.h>
#include <ArduinoJson.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
#include <Wire.h>

// --- Configuration ---
const char* ssid = "";
const char* password = "";
const char* apiKey = "";
const char* videoId = "";

// OLED Display Settings
#define SCREEN_WIDTH 128
#define SCREEN_HEIGHT 64
#define OLED_RESET    -1
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);

// Helper function to add commas to strings
String formatWithCommas(String val) {
  if (val.length() <= 3) return val;
  String res = "";
  int cnt = 0;
  for (int i = val.length() - 1; i >= 0; i--) {
    res = val[i] + res;
    cnt++;
    if (cnt % 3 == 0 && i != 0) res = "," + res;
  }
  return res;
}

void setup() {
  Serial.begin(115200);
 
  // Initialize OLED (Address 0x3C)
  if(!display.begin(SSD1306_SWITCHCAPVCC, 0x3C)) {
    Serial.println(F("SSD1306 allocation failed"));
    for(;;);
  }

  display.clearDisplay();
  display.setTextColor(WHITE);
  display.setTextSize(1);
  display.setCursor(0, 10);
  display.println("Connecting WiFi...");
  display.display();

  WiFi.begin(ssid, password);
  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }

  display.clearDisplay();
  display.setCursor(0, 10);
  display.println("WiFi Connected!");
  display.display();
  delay(1000);
}

void loop() {
  if (WiFi.status() == WL_CONNECTED) {
    fetchYoutubeStats();
  }
 
  Serial.println("Waiting 60s...");
  delay(60000);
}

void fetchYoutubeStats() {
  WiFiClientSecure client;
  client.setInsecure();

  const char* host = "www.googleapis.com";
  if (!client.connect(host, 443)) {
    Serial.println("Connection failed!");
    return;
  }

  String url = "/youtube/v3/videos?part=statistics&id=" + String(videoId) + "&key=" + String(apiKey);

  client.print(String("GET ") + url + " HTTP/1.1\r\n" +
               "Host: " + host + "\r\n" +
               "User-Agent: ESP8266\r\n" +
               "Accept: application/json\r\n" +
               "Connection: close\r\n\r\n");

  unsigned long timeout = millis();
  while (client.available() == 0) {
    if (millis() - timeout > 5000) return;
  }

  String jsonResponse = "";
  bool isBody = false;
  while (client.available()) {
    String line = client.readStringUntil('\r');
    if (line == "\n" && !isBody) {
      isBody = true;
      continue;
    }
    if (isBody) jsonResponse += line;
  }

  int startIdx = jsonResponse.indexOf('{');
  int endIdx = jsonResponse.lastIndexOf('}');
  if (startIdx != -1 && endIdx != -1) {
    jsonResponse = jsonResponse.substring(startIdx, endIdx + 1);
  }

  DynamicJsonDocument doc(2048);
  DeserializationError error = deserializeJson(doc, jsonResponse);

  if (!error && doc.containsKey("items") && doc["items"].size() > 0) {
    String rawViews = doc["items"][0]["statistics"]["viewCount"];
    String formattedViews = formatWithCommas(rawViews);

    // Update Serial
    Serial.println("Views: " + formattedViews);

    // Update OLED
    display.clearDisplay();
   
    // Header
    display.setTextSize(1);
    display.setCursor(0, 0);
    display.println("YouTube Views:");
   
    // Draw horizontal line
    display.drawLine(0, 12, 128, 12, WHITE);

    // View Count
    display.setTextSize(2);
    // Center the text roughly based on length
    int16_t x1, y1;
    uint16_t w, h;
    display.getTextBounds(formattedViews, 0, 0, &x1, &y1, &w, &h);
    display.setCursor((128 - w) / 2, 35);
    display.println(formattedViews);

    display.display();
  } else {
    Serial.println("Data fetch failed");
  }
}

🧐 How it works (The TL;DR)

The NodeMCU reaches out to Google’s servers, asks for the "statistics" of your video, and gets back a massive blob of text (JSON). Since the ESP8266 is a bit "allergic" to large web pages, we use a regex-style filter to find the { and } brackets, pull out the viewCount, and slap some commas on it so it looks pretty on the screen.

Pro-Tip: If your view count isn't going up, try making better content. (Kidding! Mostly.)













Comments