Skip to content

Pro Version

LucQuebec edited this page Jul 2, 2026 · 6 revisions

Pro Version (curl-cffi)

The Pro version is a drop-in replacement for the free library that adds native curl-cffi support, enabling yt-dlp's full impersonation feature on Android.


Why impersonation matters

Many sites protect their content by analyzing the TLS fingerprint and HTTP/2 behavior of incoming requests. A standard HTTP client (including the default Python urllib) produces a fingerprint that sites can identify as a bot. yt-dlp solves this by impersonating a real browser (Chrome, Firefox…) at the network level — reproducing the exact TLS handshake, cipher suites, and HTTP/2 settings that a browser would use.

On desktop, this is done via the curl-cffi Python library (a wrapper around curl-impersonate). On Android, no existing library supported this — until now.


Free vs Pro

Feature Free Pro
yt-dlp bundled
Java API (YtDlp)
1000+ sites (standard)
Cookie-based workaround
curl-cffi native (arm64-v8a)
Native TLS impersonation
No cookies needed for protected sites

Current ABI coverage: arm64-v8a (covers the large majority of modern Android devices).


How to get it

  1. Purchase on Gumroad ($9 one-time)
  2. You receive a personal GitHub access token by email
  3. Add the private Maven repository to your project (see below)

Integration

settings.gradle

dependencyResolutionManagement {
    repositories {
        google()
        mavenCentral()
        maven { url 'https://jitpack.io' }
        maven {
            url 'https://maven.pkg.github.com/ffmpegkit-maintained/yt-dlp-android-curl'
            credentials {
                username = "YOUR_GITHUB_USERNAME"
                password = "YOUR_ACCESS_TOKEN"  // from Gumroad purchase
            }
        }
    }
}

Tip: Store credentials in local.properties and read them with gradleLocalProperties — never commit a token to source control.

// local.properties (gitignored)
ytdlp.pro.token=ghp_xxxxxxxxxxxx
ytdlp.pro.user=your-github-username

// settings.gradle
import java.util.Properties
def localProps = new Properties()
file("local.properties").withInputStream { localProps.load(it) }

maven {
    url 'https://maven.pkg.github.com/ffmpegkit-maintained/yt-dlp-android-curl'
    credentials {
        username = localProps['ytdlp.pro.user']
        password = localProps['ytdlp.pro.token']
    }
}

build.gradle

dependencies {
    implementation 'com.lucquebec:yt-dlp-android-curl:1.0.0'
}

Usage

Replace YtDlp.init() with YtDlpCurl.init() — the rest of the API is identical:

import com.lucquebec.ytdlp.YtDlpCurl;
import com.lucquebec.ytdlp.YtDlp;
import com.lucquebec.ytdlp.YtDlpRequest;
import com.lucquebec.ytdlp.YtDlpException;

// Initialization (once, in Application.onCreate)
try {
    YtDlpCurl.init(context);  // activates curl-cffi automatically
} catch (YtDlpException e) {
    Log.e("YtDlp", "Init failed — curl-cffi unavailable on this device?", e);
}

// Check if curl-cffi was loaded successfully
if (YtDlpCurl.isCurlAvailable()) {
    Log.d("YtDlp", "Impersonation active");
} else {
    Log.w("YtDlp", "Falling back to standard mode");
}

// Download — no cookies needed for sites that require impersonation
String output = getExternalFilesDir(null) + "/%(title)s.%(ext)s";

YtDlpRequest request = new YtDlpRequest("https://example.com/video")
        .setOutputTemplate(output);

YtDlp.executeAsync(request, (progress, eta, line) -> {
    Log.d("YtDlp", progress + "% - ETA " + eta + "s");
});

Limitations

  • arm64-v8a only — The pre-built curl-cffi wheel is currently only available for 64-bit ARM Android devices. This covers the vast majority of Android 8.0+ phones. Older 32-bit devices (armeabi-v7a) and x86_64 emulators are not covered.
  • Python 3.13 required — The Pro version bundles Python 3.13 to match the curl-cffi wheel ABI. If your device runs an app targeting a different Python ABI, contact support.

Fallback strategy

If YtDlpCurl.isCurlAvailable() returns false (unsupported ABI), you can fall back to the cookie-based approach:

if (YtDlpCurl.isCurlAvailable()) {
    YtDlp.executeAsync(request, callback);
} else {
    // Fall back: prompt user to log in and provide cookies
    File cookies = exportCookiesToFile(context, "example.com");
    request.addOption("--cookies", cookies.getAbsolutePath());
    YtDlp.executeAsync(request, callback);
}

Support

For issues with the Pro version, open a ticket via Gumroad or email the address provided at purchase.

Clone this wiki locally