)<div class="api">
  <div class="container">🌞⚑This demo needs a YouTube API key to work. <a target="_blank" href="https://console.cloud.google.com/">Get yours here for free!</a>
  </div>
</div>
<section class="top-banner">
  <div class="container">
    <div class="text">
      <h1>Simple App With the YouTube API</h1>
      <p class="label">Use <mark>UC8lxnUR_CzruT2KA6cb7p0Q</mark> for testing (the Envato Tuts+ channel ID)</p>
    </div>
    <form>
      <input type="search" minlength="24" maxlength="24" placeholder="Insert a valid YT channel ID" autofocus required>
      <button type="submit">SUBMIT</button>
      <span class="msg"></span>
    </form>
  </div>
</section>
<footer class="page-footer">
  <span>made by </span>
  <a href="https://georgemartsoukos.com/" target="_blank">
    <img width="24" height="24" src="https://assets.codepen.io/162656/george-martsoukos-small-logo.svg" alt="George Martsoukos logo">
  </a>
</footer>
/* RESET & BASIC STYLES
–––––––––––––––––––––––––––––––––––––––––––––––––– */
@import url("https://fonts.googleapis.com/css2?family=Roboto:wght@400;700&display=swap");

:root {
  --total-black: #000;
  --black: #222;
  --white: #fff;
  --red: #c4302b;
  --darkred: #ae2012;
}

* {
  padding: 0;
  margin: 0;
  box-sizing: border-box;
}

button {
  cursor: pointer;
  font-size: 100%;
}

input,
input[type="search"]::-webkit-search-decoration,
input[type="search"]::-webkit-search-cancel-button,
input[type="search"]::-webkit-search-results-button,
input[type="search"]::-webkit-search-results-decoration {
  -webkit-appearance: none;
}

button,
input {
  border: none;
  background: none;
  outline: none;
  color: inherit;
  font-family: inherit;
}

img {
  max-width: 100%;
  height: auto;
}

a {
  color: inherit;
}

body {
  font: 20px/1.5 "Roboto", sans-serif;
  padding: 70px;
  background: var(--black);
}

.container {
  width: 100%;
  max-width: 1200px;
  padding: 0 15px;
  margin: 0 auto;
}

/* MAIN STYLES
–––––––––––––––––––––––––––––––––––––––––––––––––– */
.top-banner {
  color: var(--white);
}

.top-banner h1 {
  font-size: clamp(48px, 3.5vw, 72px);
  line-height: 1.2;
}

.top-banner .label {
  font-size: clamp(18px, 2vw, 28px);
  margin-top: 10px;
}

.top-banner .text {
  margin-bottom: 30px;
}

.top-banner form {
  position: relative;
  display: grid;
  grid-template-columns: 1fr auto;
  grid-gap: 15px;
  align-items: center;
  justify-content: center;
  max-width: 1000px;
}

.top-banner form input {
  font-size: clamp(24px, 2vw, 32px);
  height: 40px;
  padding-bottom: 10px;
  border-bottom: 1px solid currentColor;
}

.top-banner form input::placeholder {
  opacity: 1;
  color: var(--white);
}

.top-banner form button {
  font-weight: bold;
  padding: 15px 30px;
  border-radius: 5px;
  background: var(--red);
  transition: background 0.3s ease-in-out;
}

.top-banner form button:disabled {
  pointer-events: none;
}

.top-banner form button:hover {
  background: var(--darkred);
}

.top-banner form .msg {
  position: absolute;
  top: 100%;
  left: 0;
}

.card {
  padding: 4%;
  text-align: center;
  margin-top: 70px;
  color: var(--white);
  background: var(--total-black);
  border-radius: 7px;
  overflow: hidden;
}

.card .details img {
  border-radius: 50%;
}

.card .details .title {
  margin-top: 10px;
}

.card .details .description {
  max-width: 80%;
  margin: 30px auto 0;
}

.card .total-videos {
  position: relative;
  z-index: 1;
  margin-top: 30px;
}

.card .total-subscribers {
  position: relative;
  display: inline-grid;
  grid-template-columns: auto auto;
  grid-gap: 10px;
  align-items: center;
  font-weight: bold;
  margin-top: 60px;
  background: var(--red);
}

.card .total-subscribers dotlottie-player {
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
}

.card .total-subscribers .outer {
  padding: 10px;
}

.card .total-subscribers svg {
  fill: var(--red);
  background: var(--white);
  padding: 5px;
  box-sizing: content-box;
}

/* MQ STYLES
–––––––––––––––––––––––––––––––––––––––––––––––––– */
@media (max-width: 700px) {
  body {
    padding: 70px 15px;
  }
  .top-banner form {
    grid-template-columns: 1fr;
  }

  .top-banner form .msg {
    position: static;
  }
}

/* API BANNER STYLES
–––––––––––––––––––––––––––––––––––––––––––––––––– */
.api {
  background: #fffbbc;
  position: fixed;
  top: 0;
  left: 0;
  width: 100%;
  padding: 10px;
  font-size: 16px;
  z-index: 1;
}

.api a {
  text-decoration: underline;
}

.api a:hover {
  text-decoration: none;
}

/* FOOTER STYLES
–––––––––––––––––––––––––––––––––––––––––––––––––– */
.page-footer {
  position: fixed;
  right: 0;
  bottom: 50px;
  display: flex;
  align-items: center;
  padding: 5px;
  z-index: 1;
  font-size: 16px;
  background: var(--white);
}

.page-footer a {
  display: flex;
  margin-left: 4px;
}
import { DotLottiePlayer } from "https://unpkg.com/@dotlottie/player-component@latest/dist/dotlottie-player.mjs";
const topBanner = document.querySelector(".top-banner");
const form = topBanner.querySelector("form");
const input = topBanner.querySelector("input");
const msg = topBanner.querySelector(".msg");
const BASE_URL =
  "https://www.googleapis.com/youtube/v3/channels?part=statistics,snippet";
const API_KEY = "PUT YOUR API HERE!!!";

form.addEventListener("submit", (e) => {
  e.preventDefault();
  const channelId = input.value;

  fetchYTStatistics(channelId)
    .then((data) => {
      if (typeof data.items !== "undefined") {
        createCard(data);
      } else {
        msg.textContent = "Please search for a valid YT channel ID 😩";
      }
    })
    .catch((error) => {
      msg.textContent = error;
    });

  if (document.querySelector(".card")) {
    document.querySelector(".card").remove();
  }
  msg.textContent = "";
  form.reset();
  input.focus();
});

async function fetchYTStatistics(channelId) {
  const url = `${BASE_URL}&id=${channelId}&key=${API_KEY}`;
  const response = await fetch(url);

  if (!response.ok) {
    return Promise.reject(
      `Something isn't working as expected. Error: ${response.status}`
    );
  }
  const data = await response.json();
  return data;
}

function createCard(data) {
  const allData = data.items[0];
  const { customUrl, title, description, thumbnails } = allData.snippet;
  const { default: thumbnail } = thumbnails;
  const { videoCount, subscriberCount } = allData.statistics;
  const div = document.createElement("div");
  div.classList.add("card", "container");

  const markup = `
    <div class="details">
      <img width="${thumbnail.width}" height="${thumbnail.height}" src="${
    thumbnail.url
  }" alt="${title}">
      <div class="title">
        <a href="https://www.youtube.com/${customUrl}" target="_blank">${title}</a>
      </div>
      <p class="description">${description}</p>
    </div>
    <div class="total-videos">
      <a href="https://www.youtube.com/${customUrl}/videos" target="_blank">Browse</a>
      <span class="count">${formatNumber(videoCount)}</span> videos
    </div>
    <div class="total-subscribers">
      ${
        subscriberCount >= 1000000
          ? `<dotlottie-player src="https://lottie.host/5fa38a1c-c8ba-4c3d-83b5-1a99b8796da3/jJFC2WMsxa.lottie" background="transparent" speed="1" style="width: 300px; height: 300px;" loop autoplay></dotlottie-player>`
          : ""
      }
      <span class="outer">
        <span class="count">${formatNumber(subscriberCount)}</span>
        Subscribers
      </span>
      <svg xmlns="http://www.w3.org/2000/svg" width="40" height="40" viewBox="0 0 24 24">
        <path d="M4.652 0h1.44l.988 3.702.916-3.702h1.454l-1.665 5.505v3.757h-1.431v-3.757l-1.702-5.505zm6.594 2.373c-1.119 0-1.861.74-1.861 1.835v3.349c0 1.204.629 1.831 1.861 1.831 1.022 0 1.826-.683 1.826-1.831v-3.349c0-1.069-.797-1.835-1.826-1.835zm.531 5.127c0 .372-.19.646-.532.646-.351 0-.554-.287-.554-.646v-3.179c0-.374.172-.651.529-.651.39 0 .557.269.557.651v3.179zm4.729-5.07v5.186c-.155.194-.5.512-.747.512-.271 0-.338-.186-.338-.46v-5.238h-1.27v5.71c0 .675.206 1.22.887 1.22.384 0 .918-.2 1.468-.853v.754h1.27v-6.831h-1.27zm2.203 13.858c-.448 0-.541.315-.541.763v.659h1.069v-.66c.001-.44-.092-.762-.528-.762zm-4.703.04c-.084.043-.167.109-.25.198v4.055c.099.106.194.182.287.229.197.1.485.107.619-.067.07-.092.105-.241.105-.449v-3.359c0-.22-.043-.386-.129-.5-.147-.193-.42-.214-.632-.107zm4.827-5.195c-2.604-.177-11.066-.177-13.666 0-2.814.192-3.146 1.892-3.167 6.367.021 4.467.35 6.175 3.167 6.367 2.6.177 11.062.177 13.666 0 2.814-.192 3.146-1.893 3.167-6.367-.021-4.467-.35-6.175-3.167-6.367zm-12.324 10.686h-1.363v-7.54h-1.41v-1.28h4.182v1.28h-1.41v7.54zm4.846 0h-1.21v-.718c-.223.265-.455.467-.696.605-.652.374-1.547.365-1.547-.955v-5.438h1.209v4.988c0 .262.063.438.322.438.236 0 .564-.303.711-.487v-4.939h1.21v6.506zm4.657-1.348c0 .805-.301 1.431-1.106 1.431-.443 0-.812-.162-1.149-.583v.5h-1.221v-8.82h1.221v2.84c.273-.333.644-.608 1.076-.608.886 0 1.18.749 1.18 1.631v3.609zm4.471-1.752h-2.314v1.228c0 .488.042.91.528.91.511 0 .541-.344.541-.91v-.452h1.245v.489c0 1.253-.538 2.013-1.813 2.013-1.155 0-1.746-.842-1.746-2.013v-2.921c0-1.129.746-1.914 1.837-1.914 1.161 0 1.721.738 1.721 1.914v1.656z" />
      </svg>
    </div>
  `;

  div.innerHTML = markup;
  document.body.appendChild(div);
}

function formatNumber(number) {
  return new Intl.NumberFormat("en", {
    notation: "compact"
  }).format(number);
}

External CSS

This Pen doesn't use any external CSS resources.

External JavaScript

This Pen doesn't use any external JavaScript resources.