YouTube Trending Scraper: one country at a time

YouTube Trending Scraper returns the videos currently trending in a given country, each with its numeric view and like counts, its duration in seconds, and the channel behind it.

apidojo/youtube-trending-scraper

Estimated run cost

$0.00

Free Apify plan: 5 runs a month, 10 items a run. No credit card.

$0.025
per region queried
~50
videos included in that
$0.0005
per video after
100%
run success, last 30 days

Read on 27 September 2026.

A country code, and two things that are not targeting

The whole input surface is three fields. Worth stating what is absent as clearly as what is present, because a reader arriving from any sibling page will look for a URL field that does not exist.

  • The only input that targets anything

    gl

    $0.025per region

    ~50 videos in

    The country whose trending page to read. A two-letter code, defaulting to us.

    gl: "DE"

  • maxItems

    ÷ $0.0005past the free 50

    Run-wide

    How far down the trending page to go. Fifty come free, so this only starts costing once you want the tail.

    200

  • customMapFunction

    freeno charge

    Transform, never filter

    Reshapes each row on the way out, the natural place to stamp the region and a scrape timestamp onto every record.

    (o) => ({...o, gl: "DE" })

  • No URL input

    n/aby design

    Nothing to name

    There is no startUrls, no keywords, no youtubeHandles. Trending is not something you can point at. It is a page YouTube builds for a country.

    None

Because gl takes one string rather than an array, covering four countries means four runs. The listing prices that as four queries, which is what it costs either way, and it leaves each dataset unambiguously about one country.

YouTube Trending Scraper specificationsapidojo/youtube-trending-scraper
Apify actorapidojo/youtube-trending-scraper
Inputsgl · maxItems · customMapFunction
TargetingA country code. There is no URL, keyword or handle input
One run, one countrygl is a string, so several regions means several runs
ReturnsVideo records in trending order, with no rank field on them
Typesviews, likes and duration are numbers
Shelf lifeThe listing notes trending data changes daily
Reliability100% of 1,137 runs succeeded in the last 30 days

Today’s list, the long tail, or the same day everywhere

Three runs off one input. What separates them is how deep you go and how many countries you ask, and the free fifty means the answers differ more in shape than in price.

How do you scrape YouTube trending videos?

Set gl to a country code and run it. The query costs $0.025 and brings about fifty videos, which is most of a trending page, so the common case costs one query fee and no item charges.

Input

{
  "gl": "us",
  "maxItems": 50
}

1 × $0.025=$0.025

What comes back

The video record, Nine guaranteed fields, numeric where it counts.

{
  "id": "lL2ZwXj1tXM",
  "title": "Three Days Grace - Never Too Late",
  "url": "https://www.youtube.com/watch?v=lL2ZwXj1tXM",
  "duration": 211,
  "views": 272272914,
  "status": "OK",
  "isLive": false,
  "isPrivate": false
}

There is no rank field, keep the order you were given

Trending is a ranking, and none of the twelve documented fields records a position. The sequence exists only as dataset order, so anything that sorts or re-inserts the rows before storing them destroys the one thing the run was for. Add an index at ingest, in the order the records arrive.

How far down the trending page can you go?

Raise maxItems. Past the free fifty each video is $0.0005, so two hundred videos costs $0.10, four times the fee of the first page for four times the depth, which is where the genuinely interesting entries usually sit.

Input

{
  "gl": "us",
  "maxItems": 200
}

$0.025 + 150 × $0.0005=$0.10

What comes back

The channel block, Two guaranteed fields plus the URL, enough to spot a repeat performer.

{
  "channel": {
    "id": "UCK-VRwguZP3cokOAxI0F1HA",
    "name": "ThreeDaysGraceVEVO",
    "url": "https://www.youtube.com/channel/UCK-VRwguZP3cokOAxI0F1HA"
  },
  "keywords": ["three days grace", "rock", "music"]
}

Livestreams distort every average

isLive is guaranteed on every record, and trending pages carry streams whose view counts behave nothing like a published video’s. Filter on it before computing any average, or one concert will define your dataset.

Can you compare trending across countries?

Yes, as separate runs, gl takes one code. Four regions at their free fifty each is two hundred videos for $0.10, with no item charges, and each dataset is unambiguously about one country.

Input

{
  "gl": "DE",
  "maxItems": 50
}

4 × $0.025=$0.10

What comes back

The conditional fields, The two the listing does not guarantee.

{
  "description": "Three Days Grace's official music video...",
  "keywords": ["three days grace", "rock", "music", "official video"]
}

Run it on a schedule or it is worth nothing tomorrow

The listing’s own guidance is that trending data changes daily and recommends scheduled runs. A single snapshot tells you very little; the same four regions captured every day for a month is a dataset, and at ten cents a day it is an unusually cheap one.

Twelve documented fields, and the one that is missing

The availability table is generous. The numbers are all guaranteed. The gap is not in what the fields contain but in what no field contains: where the video sat on the page.

  • 3

    Always present

    Identity

    • id
    • title
    • url
  • 3

    Always present

    Numbers

    • views
    • likes
    • duration, seconds
  • 4

    Always present

    Context

    • channel.id, channel.name
    • thumbnails
    • isLive
  • 0

    Nowhere in the record

    Handle it yourself

    • No trending rank or position
    • No country on the row
    • No capture timestamp
Field referenceDocumented in the actor README
id · title · urlVideo ID, title and watch link. All guaranteed
viewsView count as a number, read at the moment of the run
likesLike count, documented as an always-present number
durationSeconds as a number, the quickest way to separate Shorts from long-form on a trending page
statusRecord status, "OK" in the listing’s sample
channel.id · channel.nameThe uploader, both guaranteed. Group on the ID to find channels that trend repeatedly
channel.urlChannel link, present in the sample beside the two guaranteed fields
thumbnailsArray of sizes, each with url, width and height
isLiveLivestream flag. Guaranteed, and worth filtering on first
isPrivateShown in the sample alongside isLive
description · keywordsThe two conditional fields, guard both before reading them

channel.id is what turns daily snapshots into an argument: the same channel appearing on the trending page four days in five is a finding, and it is invisible in any single run. It only exists once you have kept the history.

Three things to add yourself

This actor returns less context than its siblings because it has less to work with, one country code produces a page, not an answer to a question you asked. Three pieces of context are yours to attach.

  • 01

    Record the order

    No field carries the trending position. Index the rows as they arrive, before anything sorts or re-inserts them, or the ranking is gone.

  • 02

    Record the country

    Nothing on a row names the region. Since gl takes one string and a run covers one country, the safest place to stamp it is customMapFunction, which the listing permits for transformation.

  • 03

    Record the time

    There is no capture timestamp either, and the listing notes trending data changes daily. Without your own timestamp, two runs cannot be told apart.

  • 04

    Filter livestreams before averaging

    isLive is guaranteed for a reason. A live concert or a sports feed on a trending page carries view counts that will dominate any aggregate you compute.

  • 05

    Schedule it

    The listing recommends scheduled runs for continuous monitoring. A single snapshot of a trending page is a curiosity; a month of them is data.

Free accounts run in demo mode: 5 runs a month, 10 items each.

Cheap enough to run every day

Five scenarios from the listing, all reproducing from the two charge events. The figure to hold on to is the last one: a daily four-country snapshot is ten cents, which is three dollars a month for a continuous record.

What a run costsQuery fee + $0.0005 × billable items
RunMethodCalculationCost
50 videos1 region, the free page$0.025$0.025
100 videos1 region$0.025 + 50 × $0.0005$0.05
200 videos1 region, deep$0.025 + 150 × $0.0005$0.10
200 videos4 regions, free pages4 × $0.025$0.10
400 videos4 regions, deeper4 × $0.025 + 200 × $0.0005$0.20
500 videos10 regions, free pages10 × $0.025$0.25

Rows three and four cost the same for the same two hundred videos. One country read deep, or four read shallow. Which is better depends entirely on the question, and that is the only real decision this actor asks you to make.

Who needs to know what is popular right now?

Trending is the one dataset here you cannot reconstruct later. A channel’s uploads will still be there next month; what was trending last Tuesday will not be, unless somebody wrote it down.

  • Trend monitoring

    Today’s list, scheduled daily

    Build the historical record that does not otherwise exist, one country at a time

    $0.025 per country per day

  • Cultural and market research

    Several countries

    Compare what four markets are watching on the same day, each in its own clean dataset

    $0.10 per 4-country snapshot

  • Content strategy

    The long tail

    Read past the obvious first page to where formats are breaking through rather than already broken

    $0.10 per 200 videos

  • Media and news desks

    Today’s list

    Check what a country is actually watching before writing about what it is watching

    $0.025 per check

  • Advertising and planning

    Several countries, scheduled

    Track which channels trend repeatedly by grouping snapshots on channel.id over time

    $0.25 per 10-region sweep

Stamping what the actor cannot

The actor is apidojo/youtube-trending-scraper. Every example here does the same three things first, record the rank, the region and the time, because none of them comes back in the data.

from datetime import datetime, timezone
from apify_client import ApifyClient

client = ApifyClient("YOUR_APIFY_TOKEN")
ACTOR = "apidojo/youtube-trending-scraper"

def trending(region, depth=50):
    run = client.actor(ACTOR).call(run_input={"gl": region, "maxItems": depth})
    captured = datetime.now(timezone.utc).isoformat()

    rows = []
    # enumerate BEFORE anything sorts: dataset order is the ranking.
    for rank, v in enumerate(client.dataset(run.default_dataset_id).iterate_items(), 1):
        rows.append({**v, "rank": rank, "gl": region, "captured_at": captured})
    return rows

# gl is a string, so a multi-country study is several runs by construction.
snapshot = [row for r in ("us", "gb", "de", "jp") for row in trending(r)]

published = [v for v in snapshot if not v["isLive"]]   # streams skew everything
for v in published[:10]:
    print(f"{v['gl']}  #{v['rank']:<3} {v['views']:>12,}  {v['title'][:45]}")
import { ApifyClient } from 'apify-client';

const client = new ApifyClient({ token: process.env.APIFY_TOKEN });

const trending = async (gl, maxItems = 50) => {
  const run = await client.actor('apidojo/youtube-trending-scraper').call({ gl, maxItems });
  const { items } = await client.dataset(run.defaultDatasetId).listItems();
  const capturedAt = new Date().toISOString();
  return items.map((v, i) => ({...v, rank: i + 1, gl, capturedAt }));
};

const regions = await Promise.all(['us', 'gb', 'de'].map((r) => trending(r)));
const all = regions.flat();

// The same video trending in several countries is the interesting case.
const shared = Object.entries(Object.groupBy(all, (v) => v.id))
 .filter(([, rows]) => rows.length > 1)
 .map(([id, rows]) => ({ id, title: rows[0].title, in: rows.map((r) => r.gl) }));

console.log(shared);
curl -X POST \
  "https://api.apify.com/v2/acts/apidojo~youtube-trending-scraper/run-sync-get-dataset-items?token=YOUR_APIFY_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"gl":"us","maxItems":50}'

Apify’s scheduler is the natural home for this one, the listing recommends it directly. Export as JSON or CSV, but keep whatever you use to record the arrival order.

YouTube Trending Scraper FAQ

How much does it cost to scrape YouTube trending?

$0.025 per region, which includes about the first fifty videos, then $0.0005 each. A daily snapshot of four countries costs ten cents.

Can I scrape trending for a specific channel or topic?

No. The only targeting input is gl, a country code. There is no URL, keyword or handle field, trending is a page YouTube builds per country, not something you can point at.

Can I get several countries in one run?

No, gl takes a single string, so each country is its own run. That costs the same as the listing’s multi-region examples and leaves each dataset about exactly one country.

Does the output say where a video ranked?

No. None of the documented fields carries a position, so the ranking exists only as the order records arrive. Index them at ingest before anything re-sorts them.

Does it say which country the data came from?

Not on the row. Since one run covers one region, stamp it yourself, customMapFunction is the natural place.

Are views and likes numbers?

Yes. The availability table types views, likes and duration as numbers and marks all three always present.

How often should I run it?

The listing notes trending data changes daily and recommends scheduled runs. A single snapshot has little value; a continuous record is the point.

Why are some view counts enormous?

Trending pages include livestreams, whose counts behave differently from published videos. isLive is guaranteed on every record, filter on it before computing averages.

Check one country

Two and a half cents, fifty videos, today only.

gl: "us" · maxItems: 50

Run this scraper free

Apidojo is not affiliated with YouTube or Google LLC.