Skip to content

Pro Version

LucQuebec edited this page Jul 4, 2026 · 6 revisions

Pro Version (curl-cffi)

The Pro version is a drop-in replacement for the free library. Like the free version, it uses Chaquopy 17.0.0 + Python 3.13 — the key addition is curl-cffi, which enables TLS fingerprint impersonation. Both AARs are fully self-contained; no NDK setup or manual compilation is required.

Purchase on Gumroad — $14 individual · $36 team (5 devs) · includes Maven access token + updates


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 Python's default 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
Python 3.13 runtime (Chaquopy)
curl-cffi (arm64-v8a)
TLS fingerprint impersonation
No cookies needed for protected sites

Current ABI coverage: arm64-v8a — covers the large majority of modern Android devices (>90% of Android 8.0+ phones).


Architecture

The Pro AAR bundles a full Python 3.13 runtime via Chaquopy (MIT license, open source since v12.0.1). All Python packages (yt-dlp, curl-cffi) are pre-installed inside the AAR — the device does not need Python or pip.

Your app
  └─ yt-dlp-android-curl (AAR)
       ├─ Chaquopy runtime (Python 3.13, arm64-v8a)
       ├─ yt-dlp (pure Python)
       └─ curl-cffi 0.15.0 (arm64-v8a wheel)

Your app does not need to apply the Chaquopy plugin — the AAR is fully self-contained.


How to get it

  1. Purchase on Gumroad — Individual ($14) or Team / Company 5 devs ($36)
  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 (already gitignored by default)
ytdlp.pro.token=ghp_xxxxxxxxxxxx
ytdlp.pro.user=your-github-username
// settings.gradle — read from local.properties
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 'dev.ffmpegkit_maintained:yt-dlp-android-curl:VERSION'  // version communicated after purchase
}

Usage

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

import dev.ffmpegkit_maintained.ytdlp.YtDlpCurl;
import dev.ffmpegkit_maintained.ytdlp.YtDlp;
import dev.ffmpegkit_maintained.ytdlp.YtDlpRequest;
import dev.ffmpegkit_maintained.ytdlp.YtDlpException;

// Initialization (once, in Application.onCreate or MainActivity.onCreate)
try {
    YtDlpCurl.init(context);  // activates curl-cffi automatically
} catch (YtDlpException e) {
    Log.e("YtDlp", "Init failed", e);
}

// Optional: check that curl-cffi loaded successfully
if (YtDlpCurl.isCurlAvailable()) {
    Log.d("YtDlp", "Impersonation active");
} else {
    Log.w("YtDlp", "curl-cffi not available on this device");
}

// 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) -> {
    runOnUiThread(() -> Log.d("YtDlp", progress + "% — ETA " + eta + "s"));
});

Limitations

  • arm64-v8a only — The 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. On unsupported ABIs, YtDlpCurl.isCurlAvailable() returns false.

  • curl-cffi currently requires --pre flag on PyPI — The Android wheel is distributed as a pre-release. Once a stable release is published, a future update of the AAR will remove this constraint.


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 {
    // Prompt the user to log in and provide cookies
    File cookies = exportCookiesToFile(context, "example.com");
    request.addOption("--cookies", cookies.getAbsolutePath());
    YtDlp.executeAsync(request, callback);
}

See Cookie Authentication for the full exportCookiesToFile() implementation.


Support

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

Clone this wiki locally