Skip to content

PoTokenRequired: exp=xpe in captionTrack baseUrl returns empty body — no workaround available (v1.2.4) #592

Description

@dargui182

Description

When fetching transcripts for certain YouTube videos, the library raises PoTokenRequired instead of returning the transcript. This happens even for videos that clearly have captions visible in the YouTube UI and accessible when browsing normally.

Environment

  • youtube-transcript-api version: 1.2.4
  • Python: 3.12.6
  • OS: Windows 10 Pro 10.0.19045

Steps to reproduce

from youtube_transcript_api import YouTubeTranscriptApi
api = YouTubeTranscriptApi()
transcript = api.fetch('VIDEO_ID', languages=['it', 'en'])

The exception is raised for videos whose caption track baseUrl (inside ytInitialPlayerResponse.captions.playerCaptionsTracklistRenderer.captionTracks) contains the &exp=xpe query parameter. When this parameter is present, YouTube's timedtext endpoint returns an empty HTTP 200 response body for any programmatic request — including requests that carry valid session cookies from a logged-in browser.

Expected behaviour

api.fetch() returns transcript segments, or raises a specific exception with documented guidance on how to work around the PoToken requirement.

Actual behaviour

youtube_transcript_api._errors.PoTokenRequired

No documented way to supply a PoToken exists. Passing a requests.Session pre-loaded with valid YouTube cookies does not help, because the PoToken is not a cookie — it is a cryptographic proof-of-origin token generated at runtime by the YouTube player JavaScript and appended as a query parameter (&pot=...) to the URL.

Additional context

  • Affects only videos whose captionTracks[].baseUrl already contains &exp=xpe.
  • Distinct from IpBlocked / RequestBlocked: those indicate server-side IP banning; this is a client-side authentication requirement that no amount of IP rotation resolves.
  • The transcript IS accessible by clicking "Open transcript" in the YouTube UI in a real logged-in browser — the browser's player JS generates the PoToken transparently.
  • Closed issue No Element Found on v1.1.0 #454 reported a similar symptom. Reopening because the root cause remains unresolved as of v1.2.4.

Requested fix / workaround

  1. Document how to provide a PoToken to the library, OR
  2. Implement automatic PoToken generation (as some yt-dlp forks do via Botguard), OR
  3. Fall back to an alternative transcript-fetching strategy when exp=xpe is detected in the base URL (e.g. use the InnerTube /browse endpoint or parse the transcript panel response instead of the timedtext direct URL).

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions