yt-dlp/yt-dlp · error · DownloadError

Failed to decrypt with DPAPI. See https://github.com/yt-dlp

Error message

Failed to decrypt with DPAPI. See  https://github.com/yt-dlp/yt-dlp/issues/10927  for more info

What it means

On Windows, Chromium cookie values whose encrypted blob has no v10/v11 prefix are decrypted with DPAPI via CryptUnprotectData. That API is bound to the Windows logon that encrypted the data; when it fails (ret == 0), yt-dlp logs the message referencing issue #10927 and raises DownloadError to force exit. Common root cause: cookies encrypted under a different Windows user/elevation context, or Chrome 127+ app-bound encryption which refuses to unprotect from other processes.

Source

Thrown at yt_dlp/cookies.py:1101

        _fields_ = [('cbData', ctypes.wintypes.DWORD),
                    ('pbData', ctypes.POINTER(ctypes.c_char))]

    buffer = ctypes.create_string_buffer(ciphertext)
    blob_in = DATA_BLOB(ctypes.sizeof(buffer), buffer)
    blob_out = DATA_BLOB()
    ret = ctypes.windll.crypt32.CryptUnprotectData(
        ctypes.byref(blob_in),  # pDataIn
        None,  # ppszDataDescr: human readable description of pDataIn
        None,  # pOptionalEntropy: salt?
        None,  # pvReserved: must be NULL
        None,  # pPromptStruct: information about prompts to display
        0,  # dwFlags
        ctypes.byref(blob_out),  # pDataOut
    )
    if not ret:
        message = 'Failed to decrypt with DPAPI. See  https://github.com/yt-dlp/yt-dlp/issues/10927  for more info'
        logger.error(message)
        raise DownloadError(message)  # force exit

    result = ctypes.string_at(blob_out.pbData, blob_out.cbData)
    ctypes.windll.kernel32.LocalFree(blob_out.pbData)
    return result


def _config_home():
    return os.environ.get('XDG_CONFIG_HOME', os.path.expanduser('~/.config'))


def _open_database_copy(database_path, tmpdir):
    # cannot open sqlite databases if they are already in use (e.g. by the browser)
    database_copy_path = os.path.join(tmpdir, 'temporary.sqlite')
    shutil.copy(database_path, database_copy_path)
    conn = sqlite3.connect(database_copy_path)
    return conn.cursor()

View on GitHub (pinned to 81ecd58b13)

Solutions

  1. Run yt-dlp from a normal (non-elevated) terminal as the same Windows user that owns the browser profile
  2. Update yt-dlp to the latest nightly — handling around Chrome 127+ app-bound encryption (issue #10927) is actively improved
  3. Close the browser, or use a different supported browser (firefox) whose cookie store does not need DPAPI
  4. Durable workaround: export cookies to cookies.txt from the browser and pass --cookies cookies.txt

Example fix

# before (elevated PowerShell — DPAPI cannot see the user's key)
Start-Process powershell -Verb RunAs; yt-dlp --cookies-from-browser chrome URL
# after (normal terminal, same user as Chrome profile)
yt-dlp --cookies-from-browser chrome URL
Defensive patterns

Strategy: fallback

Validate before calling

# Windows: run yt-dlp in the same interactive, non-elevated context that owns the cookies
import ctypes, os

def dpapi_context_sane():
    # heuristics: not elevated, not SYSTEM/service
    try:
        return not ctypes.windll.shell32.IsUserAnAdmin()
    except Exception:
        return False

if os.name == 'nt' and not dpapi_context_sane():
    raise SystemExit('Run without elevation as the browser user, or use --cookies cookies.txt')

Try / catch

from yt_dlp.utils import DownloadError
try:
    ydl.download([url])
except DownloadError as e:
    if 'DPAPI' in str(e):
        # per-user Windows encryption mismatch — switch to exported cookies
        opts.pop('cookiesfrombrowser', None); opts['cookiefile'] = 'cookies.txt'
        with YoutubeDL(opts) as y2:
            y2.download([url])
    else:
        raise

Prevention

When it happens

Trigger: --cookies-from-browser chrome/edge/brave/... on Windows where the 'other' prefixed cookies (DPAPI branch in _decrypt_windows_chromium) hit CryptUnprotectData failure. Typical: running yt-dlp elevated (as admin) while the cookie store belongs to the regular user; running under a service account; profile copied from another machine/user; Chrome 127+ app-bound (v20) cookies.

Common situations: User runs the terminal 'as Administrator' so DPAPI cannot access the interactive user's master key; scheduled-task/service context; domain profile roaming; cookies synced from another device with older encryption; new Chrome app-bound encryption on fully patched systems.

Related errors


AI-assisted analysis of yt-dlp/yt-dlp@81ecd58b13 (2026-08-22). Data as JSON: /api/errors/116138f6bfa69641. Report an issue: GitHub.