Blog / Tutorials / Paginating Large YouTube Transcript Batches
Tutorials 6 min read â€ĸ November 13, 2026

Paginating Large YouTube Transcript Batches

Founder

A batch with hundreds of videos doesn't come back in one response. GET /api/v1/transcripts/{batch_id} pages its items with skip/limit, and tells you when you're done with has_more. This is the pattern to use for anything beyond a small test batch — a channel batch can easily hold thousands of videos.

This isn't an arbitrary limit for its own sake: without it, polling a 1,000-video batch would mean one response carrying a thousand transcripts' worth of text (plus metadata, if you asked for it), which is slow to generate, slow to transfer, and awkward to hold in memory all at once. Paging spreads that cost across however many requests you actually need.

Paging through one batch's items

curl -s "https://scriptube.me/api/v1/transcripts/BATCH_ID?skip=0&limit=50" \
  -H "X-API-Key: YOUR_API_KEY"

limit defaults to (and caps at) 50 items per page. The response carries:

FieldMeaning
itemsThis page's items.
item_countTotal items in the whole batch.
skip / limitEchoes what you asked for.
has_moretrue if there's another page after this one.

Loop until has_more is false:

import requests

HEADERS = {"X-API-Key": "YOUR_API_KEY"}
BASE = "https://scriptube.me"
batch_id = "00000000-0000-0000-0000-000000000000"

items = []
skip = 0
limit = 50  # max page size = resolve_inline_cache_limit (default 50)

while True:
    page = requests.get(
        f"{BASE}/api/v1/transcripts/{batch_id}",
        headers=HEADERS,
        params={"skip": skip, "limit": limit},
    ).json()
    items.extend(page["items"])
    if not page["has_more"]:
        break
    skip += limit

print(f"loaded {len(items)} of {page.get('item_count')} items")

If you only need metadata or timestamps, add include_metadata=true or include_segments=true to the same request — they apply per page, not per batch, so the cost of a bigger payload is spread across your loop instead of landing in one giant response.

A concrete worked case: a 4,000-video channel batch, at the default 50 per page, is 80 requests to walk end to end. At 60 reads/minute that's under two minutes sequentially — comfortably inside the limit for a one-off export, but worth knowing if you're paginating several large batches from the same key at once, since they share the same per-key budget.

A different page: the list of batches

GET /api/v1/transcripts (no ID) lists your batches themselves — summary rows, no items, no transcript text. It has its own skip/limit (default 20, max 100) and its own has_more/total, independent of how many items are inside any one batch:

# Paginating the batch LIST itself (a different endpoint, a different page shape)
batches = []
skip = 0
while True:
    page = requests.get(
        f"{BASE}/api/v1/transcripts",
        headers=HEADERS,
        params={"skip": skip, "limit": 100},
    ).json()
    batches.extend(page["batches"])
    if not page["has_more"]:
        break
    skip += 100

Filter this list to one partner's batches with external_id=, or to the batches created by a single mixed submission with submission_id= — see tagging batches.

Processing pages as you go, not after

Don't accumulate every item into one list before doing anything with it if the batch is large — process each page as it arrives and discard it:

skip = 0
completed, failed = 0, 0
while True:
    page = requests.get(
        f"{BASE}/api/v1/transcripts/{batch_id}",
        headers=HEADERS,
        params={"skip": skip, "limit": 50},
    ).json()
    for item in page["items"]:
        if item["status"] == "completed":
            completed += 1
            # write item["transcript_text"] to storage here, not to a growing list
        else:
            failed += 1
    if not page["has_more"]:
        break
    skip += 50

print(f"{completed} completed, {failed} failed/skipped")

This keeps memory flat regardless of batch size, and means a script that's writing results to disk or a database doesn't lose everything if it crashes on page 70 of 80 — pages 1 through 69 are already saved.

Common mistakes

  • Assuming one page is the whole batch. Always check has_more; a batch of 300 videos is 6 pages at the default limit.
  • Re-requesting metadata on every poll while still processing. Poll with no extra params first; only pull include_metadata/include_segments once you're paging through a completed batch — a larger payload per page is wasted while most items are still queued.
  • Confusing item pagination with batch-list pagination. They're separate endpoints with separate skip/limit values — incrementing one doesn't affect the other.
  • Hardcoding limit=50 as a guess. It's the documented default/max, not an arbitrary round number — raising it in your request doesn't get you a bigger page, it just gets capped back down to 50.

Pagination on exports

Exports (GET /api/v1/transcripts/{batch_id}/export) are streamed rather than paginated with skip/limit — request a format and the whole file comes back as one response, built incrementally server-side rather than loaded into memory all at once. You don't need a pagination loop for exports; it's only the JSON-shaped batch poll (GET /api/v1/transcripts/{batch_id} with no ?format=) that pages.

Frequently asked

What's the actual max limit value? 50 for item pagination (resolve_inline_cache_limit), 100 for the batch list. Asking for more than the max is simply capped, not rejected.

Does pagination cost credits? No — reading a batch, at any page, any number of times, is always free. Only the original submit charges credits.

Can I paginate backward, or jump to a specific item? Only forward by skip. If you need to resume a crashed job, store the last successfully processed skip value and restart from there.

Does the item order change between pages if the batch is still processing? Item order within a batch is stable once set at submission, so paging through a still-running batch is safe — you won't see items shift position or duplicate across pages as more of them complete.

Next steps

Full reference: API documentation.

Try Scriptube Free

Extract YouTube transcripts instantly. No credit card required.

Get Started

Related Articles

Tutorials

Your YouTube Transcript Library: Find Everything You've Already Processed

Every video you've ever submitted to Scriptube stays in your library — browsable by channel and playlist, searchable when you need to find something you...

Tutorials

How to Retry Failed YouTube Transcripts Without Resubmitting the Batch

A batch of 50 videos rarely comes back 50 for 50 — a couple of videos might have no captions, one might hit a rate limit, another might just need a second...

Tutorials

YouTube Transcript API: The Complete Guide

The Scriptube API lets you submit YouTube video, playlist, or channel URLs and get back transcripts and metadata as JSON, CSV, or JSONL, plus timed segments...