Recently on YouTube I searched “population apportionment” to find that many of the recommended videos across different channels looked the same and appeared to be AI-generated, heavily automated, and extremely low effort. Of the 18 Recently Uploaded videos for the search, 10 of theme were all from this same “family” of channels: 2 to 3 minute, political-themed questions with an AI-generated man or women in the thumbnail, leading to an animated PowerPoint presentation.

Clearly, I am late to catching onto this. The Guardian published an article indicating one in ten of the fastest growing YT channels are AI-generated back in August ‘25; John Oliver did a segment on it back in June on social media networks.

When is the line to assume that content is AI-generated, or at least heavily automated? Is it plausible to believe that all of these channels have teams of people exhaustively researching these questions, copy pasting, and uploading by hand?

As of 12/17/25, I saw within a couple minutes the following channels, all with nearly the exact same format and branding:

  • Election Central Channel (47 subscribers, 10k videos, 14,575 views, channel started 4/15/2025)
  • America First Democrats (372 subscribers, 17k videos, 82,030 views, channel started 2/5/2025)
  • Stories of the States (400 subscribers, 18k videos, 112,900 views, channel started 1/16/2025)
  • Making Politics Simple (1.69k subscribers, 22k videos, 301,461 views, channel started 1/29/2025)
  • Demographic Data Answers (105 subscribers, 10k videos, 31,702 views, channel started 5/21/2025)
  • The Geography Atlas (1.4k subscribers, 24k videos, 335,900 views, channel started 1/27/2025)
  • Inside the Legislative Branch (135 subscribers, 11k videos, 26,220 views, channel started 3/13/2025)

The emails of all of the channels all point to the same email provider and hosting company Vultr based on a DNS and WHOIS records. All emails are generic “team, about, info@…” for the channel name.

For Demographic Data Answers, 5 videos have been published in the last hour alone, and it pretty consistently is like this for 2, 3,4 hours ago and so on. Let’s just assume these are on a scheduled release across all the channels.

Chart showing rate of published videos since each channels’ inception, ranging from 39 to 74 videos per day

The Geography Atlas Channel is averaging 74 videos per day, based on the total number of videos published on the channel and their channel starting in January 2025.

I built in Observable Plot Notebooks, just copied over the data after using an LLM to convert the bullet point list above to a JS array. Only interesting thing about creating this chart is the rotation of the text labels. While the plot has a scale object itself you can surface, I couldn’t figure out a way to access the scale of the plot itself within the rotate option for the text mark.

// returns x-scale
plotObj.scale("x")

// returns something like (depending on the scale type)

Object {
  type: "utc"
  domain:  Array(2) [2025-01-16, 2025-12-17]
  range: Array(2) [0, 730]
  interpolate: ƒ(t, n)
  clamp: false
  apply: ƒ(e)
  invert: ƒ(e)
}
// The .apply function lets you pass a value and returns the transformed value to the plotted coordinate on the screen, which is what I needed.

The “x” is the scale name; all are available in the documentation here.

So instead I created two separate scale objects, 1 for the X and one for the Y, and pass the same width, height, margins, domains and ranges to each scale and to the chart itself, so that they all matched.

xScale = Plot.scale({
  x: {
    // could use min / max next time But.
    domain: [new Date("2025-01-16"), new Date()],
    range: [0, width - marginRight]
  }
})

yScale = Plot.scale({
  y: {
    domain: [0, 24000],
    range: [0, height - marginTop]
  }
})

I did need to brush up on some geometry and JavaScript trig functions and look up how to convert the radians to degrees. It’s also negative to make sure that the labels rotate correctly.

rotate: (d) =>
    -(
    Math.atan2(
        yScale.apply(d.totalVideos) - yScale.apply(0),
        xScale.apply(new Date()) - xScale.apply(d.date)
    ) *
    (180 / Math.PI)
    )

One other note is that dy and dx are not data-driven. Since the bottom two lines overlap, I set a constant dy to put the labels slightly above each line for readability. I then just set a ternary operator to decrease the y value of the Videos Published of the Demographic Data Answers line, subtracting ~500 videos or so to lower it manually. Not scalable, but I’m not sure of a simpler way to do it, and this is a quick post.

There is some news about YouTube trying to limit low-effort AI content; for exmaple, from July 15th, 2025 on updating guidelines for monetization. I am now extremely curious about what tools YouTube uses to label and remove spam channels like this at scale.

Youtube doesn’t seem to offer a specific report for mass AI-generated content. They have “Spam and Scam”, which I guess is the closest? It allows you to select videos, but not all videos. And it allows you to submit a comment, but I don’t know exactly what should be included.

Funnily, here is a likely AI-generated article full of AI images about YouTube fighting against AI content. Nuts.