Skip to content

Add androidSdkless client to fix 403 errors on audio-only streams - #371

Merged
Hexer10 merged 3 commits into
Hexer10:masterfrom
binSaed:master
Feb 25, 2026
Merged

Add androidSdkless client to fix 403 errors on audio-only streams#371
Hexer10 merged 3 commits into
Hexer10:masterfrom
binSaed:master

Conversation

@binSaed

@binSaed binSaed commented Jan 11, 2026

Copy link
Copy Markdown
Contributor

Audio-only streams return 403 while muxed streams work. Root cause: the android client includes androidSdkVersion which triggers YouTube's PO Token requirement.

Changes

  • Added YoutubeApiClient.androidSdkless — Android client without androidSdkVersion field, based on yt-dlp's working implementation
  • Changed default client from android to androidSdkless in StreamClient.getManifest()

Reference

From yt-dlp's _base.py:

# Doesn't require a PoToken for some reason
'android_sdkless': {
    'INNERTUBE_CONTEXT': {
        'client': {
            'clientName': 'ANDROID',
            'clientVersion': '20.10.38',
            # Note: no androidSdkVersion
            'userAgent': 'com.google.android.youtube/20.10.38 (Linux; U; Android 11) gzip',
            ...
        },
    },
    ...
}

The original android client is preserved for users who need it explicitly.

Copilot AI and others added 3 commits January 11, 2026 09:23
Co-authored-by: binSaed <33700292+binSaed@users.noreply.github.com>
Add androidSdkless client to fix 403 errors on audio-only streams
Copilot AI review requested due to automatic review settings January 11, 2026 09:42

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR adds a new androidSdkless YouTube API client to fix 403 errors that occur when streaming audio-only content. The root cause is that the existing android client includes an androidSdkVersion field which triggers YouTube's PO Token requirement.

Changes:

  • Added YoutubeApiClient.androidSdkless client based on yt-dlp's working implementation that omits the androidSdkVersion field
  • Changed the default client from android to androidSdkless in StreamClient.getManifest()
  • Updated documentation for the existing android client to note PO Token requirements

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated 1 comment.

File Description
lib/src/videos/youtube_api_client.dart Adds new androidSdkless client constant and updates android client documentation
lib/src/videos/streams/stream_client.dart Changes default client to androidSdkless for better compatibility

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.


videoId = VideoId.fromString(videoId);
final clients = ytClients ?? [YoutubeApiClient.android];
final clients = ytClients ?? [YoutubeApiClient.androidSdkless];

Copilot AI Jan 11, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Consider adding a specific test case that validates the androidSdkless client works correctly with audio-only streams to prevent regressions of the 403 error issue this PR aims to fix. The test could use ytClients parameter to explicitly test both the old android client (expecting potential 403 errors) and the new androidSdkless client (expecting success).

Copilot uses AI. Check for mistakes.
@binSaed

binSaed commented Jan 11, 2026

Copy link
Copy Markdown
Contributor Author

Issue

Code

final manifests = await _yt.videos.streams.getManifest( videoId);
final availableManifests = List<AudioStreamInfo>.of([]);

  await Future.wait([
    for (final manifest in manifests.audio)
      http.head(manifest.url).then((res) {
        print('$manifest : ${res.statusCode}');
        if (res.statusCode > 299 || res.statusCode < 200) return;
        availableManifests.add(manifest);
      }),
  ]);

Result

flutter: Muxed (18 | 640x360p30 | mp4) : 200 
flutter: Audio-only (599 | mp4 | null) : 403 
flutter: Audio-only (139 | mp4 | null) : 403 
flutter: Audio-only (140 | mp4 | null) : 403 
flutter: Audio-only (600 | webm | null) : 403 
flutter: Audio-only (249 | webm | null) : 403 
flutter: Audio-only (251 | webm | null) : 403

@Hexer10
Hexer10 merged commit 990bd42 into Hexer10:master Feb 25, 2026
5 of 6 checks passed
@lkvdy

lkvdy commented May 1, 2026

Copy link
Copy Markdown

شكرااا

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants