wkentaro/gdown

Google Drive public file downloader when curl/wget fails.

Python

5,447

801 commits

updated Sep 29, 2026

See the code

README

gdown

PyPI Python Build License

Google Drive public file/folder downloader when curl/wget fails.

Why?

Downloading public files from Google Drive with curl or wget doesn't work — Google serves a confirmation page for large files, and the URL formats are a mess.

gdown gets around that:

  • Skips the virus-scan confirmation page so large downloads actually finish
  • Downloads folders recursively
  • Exports Google Docs/Sheets/Slides as PDF, DOCX, CSV, etc.
  • Resumes partial downloads with --continue
  • Also works with plain HTTP/HTTPS URLs as a curl/wget replacement

Install

Requires Python 3.10 or later.

pip install gdown

Or with uv:

uv tool install gdown

Quick start

# Just paste a Google Drive URL
gdown https://drive.google.com/uc?id=1l_5RK28JRL19wpT22B-DY9We3TVXnnQQ

# Or copy-paste a share link directly
gdown 'https://drive.google.com/file/d/0B9P1L--7Wd2vU3VUVlFnbTgtS2c/view?usp=sharing'

Usage

CLI

Files

# Download by URL
gdown https://drive.google.com/uc?id=1l_5RK28JRL19wpT22B-DY9We3TVXnnQQ

# Download by file ID
gdown 1l_5RK28JRL19wpT22B-DY9We3TVXnnQQ

# Download from a share link
gdown 'https://drive.google.com/file/d/0B9P1L--7Wd2vU3VUVlFnbTgtS2c/view?usp=sharing'

# Save to a specific path
gdown https://drive.google.com/uc?id=0B9P1L--7Wd2vU3VUVlFnbTgtS2c -O /tmp/spam.txt

# Resolve the filename (with its real extension) without downloading
gdown https://drive.google.com/uc?id=0B9P1L--7Wd2vU3VUVlFnbTgtS2c --json

--json is in beta and its output format may change in a future release; pass --quiet to silence the beta warning in scripts. The output is an array of {url, path} entries, where path is the filename Google Drive reports. This lets you choose a name while keeping the original extension:

url="https://drive.google.com/uc?id=0B9P1L--7Wd2vU3VUVlFnbTgtS2c"
filename=$(gdown "$url" --json | jq -r '.[0].path')
gdown "$url" -O "my_name.${filename##*.}"

Folders

# Download an entire folder
gdown https://drive.google.com/drive/folders/15uNXeRBIhVvZJIhL4yTw4IsStMhUaaxl -O /tmp/folder

# List folder contents as a JSON array (each entry has url and path)
gdown https://drive.google.com/drive/folders/15uNXeRBIhVvZJIhL4yTw4IsStMhUaaxl --json

# Filter by path and download matches
gdown https://drive.google.com/drive/folders/15uNXeRBIhVvZJIhL4yTw4IsStMhUaaxl --json \
  | jq -r '.[] | select(.path | test("shad")) | .url' \
  | xargs -n1 gdown

Folder URLs are detected automatically. A bare folder ID still requires --folder because file and folder IDs have the same format.

Google Docs, Sheets, Slides

# Download a Google Slides file (default: pptx)
gdown "https://docs.google.com/presentation/d/15umvZKlsJ3094HNg5S4vJsIhxcFlyTeK/edit?usp=sharing"

# Export as PDF instead
gdown "https://docs.google.com/presentation/d/15umvZKlsJ3094HNg5S4vJsIhxcFlyTeK/edit" --format pdf

Default export formats: Docs → docx, Sheets → xlsx, Slides → pptx.

Resume, speed limit, proxy

# Resume a partially downloaded file
gdown https://drive.google.com/uc?id=1l_5RK28JRL19wpT22B-DY9We3TVXnnQQ --continue

# Limit download speed
gdown https://drive.google.com/uc?id=1l_5RK28JRL19wpT22B-DY9We3TVXnnQQ --speed 10MB

# Download via proxy
gdown https://drive.google.com/uc?id=1l_5RK28JRL19wpT22B-DY9We3TVXnnQQ --proxy http://proxy:8080

# Give up when the server sends nothing for 30 seconds
gdown https://drive.google.com/uc?id=1l_5RK28JRL19wpT22B-DY9We3TVXnnQQ --timeout 30

Other options

# Skip TLS certificate verification
gdown https://drive.google.com/uc?id=1l_5RK28JRL19wpT22B-DY9We3TVXnnQQ --no-check-certificate

# Download as your signed-in Google account, reusing your browser's cookies
gdown https://drive.google.com/uc?id=1l_5RK28JRL19wpT22B-DY9We3TVXnnQQ --cookies-from-browser firefox

# Read and save cookies in a file other than ~/.cache/gdown/cookies.txt
gdown https://drive.google.com/uc?id=1l_5RK28JRL19wpT22B-DY9We3TVXnnQQ --cookies ./cookies.txt

# Don't read or save cookies
gdown https://drive.google.com/uc?id=1l_5RK28JRL19wpT22B-DY9We3TVXnnQQ --no-cookies

# Use a custom User-Agent
gdown https://drive.google.com/uc?id=1l_5RK28JRL19wpT22B-DY9We3TVXnnQQ --user-agent "MyApp/1.0"

Pipe to stdout

gdown https://github.com/wkentaro/gdown/archive/refs/tags/v4.0.0.tar.gz -O - --quiet | tar zxvf -

Any URL

gdown also works with regular URLs, not just Google Drive:

gdown https://httpbin.org/ip -O ip.json

[!NOTE] For Google Drive URLs, gdown automatically extracts the file ID and downloads the actual file. Use curl or wget to download the raw HTML page instead.

Python

import gdown

# Download a file
url = "https://drive.google.com/uc?id=1l_5RK28JRL19wpT22B-DY9We3TVXnnQQ"
gdown.download(url=url, output="fcn8s_from_caffe.npz")

# Download by file ID
gdown.download(id="0B9P1L--7Wd2vNm9zMTJWOGxobkU", output="output.npz")

# Download from a share link
url = "https://drive.google.com/file/d/0B9P1L--7Wd2vNm9zMTJWOGxobkU/view?usp=sharing"
gdown.download(url=url, output="output.npz")

# Download with hash verification and caching
gdown.cached_download(
    url=url,
    path="output.npz",
    hash="md5:fa837a88f0c40c513d975104edf3da17",
    postprocess=gdown.extractall,
)

# Track download progress
def on_progress(bytes_so_far: int, bytes_total: int | None) -> None:
    if bytes_total is not None:
        print(f"\r{bytes_so_far / bytes_total * 100:.1f}%", end="")

gdown.download(url=url, output="output.npz", quiet=True, progress=on_progress)

# Download a folder
url = "https://drive.google.com/drive/folders/15uNXeRBIhVvZJIhL4yTw4IsStMhUaaxl"
gdown.download_folder(url=url)

# Download a folder by ID
gdown.download_folder(id="15uNXeRBIhVvZJIhL4yTw4IsStMhUaaxl")

FAQ

"Permission Denied" error

Make sure the file sharing is set to "Anyone with the link".

Google throttles downloads when too many people access the same file, but lets a signed-in account through. If you can still open the file in your browser, reuse that browser's cookies:

gdown --cookies-from-browser firefox https://drive.google.com/uc?id=FILE_ID

Supported browsers: brave, chrome, chromium, edge, firefox, opera, safari, vivaldi, whale. gdown saves the cookies to ~/.cache/gdown/cookies.txt, so later runs need no flag. That file then holds your whole google.com session, Gmail and Account included, so treat it like a password. To revoke it, delete the file and sign out of Google in that browser.

Platform notes:

  • Linux Chromium-family browsers using GNOME Keyring require secretstorage in gdown's Python environment. Install with pip install 'gdown[secretstorage]' or run uvx --from 'gdown[secretstorage]' gdown --cookies-from-browser chrome URL. Firefox needs no extra dependency.
  • macOS asks for your login password once to unlock the Chromium-family keychain entry; Firefox needs nothing.
  • Windows Chrome 127+ encrypts cookies so other programs cannot read them. Use Firefox there.
  • Safari requires Full Disk Access for your terminal.

If none of that works, export a Netscape cookies.txt with a browser extension such as Get cookies.txt LOCALLY and pass it with --cookies cookies.txt. gdown rewrites that file while resolving each Google Drive file, whether or not it downloads it.

Download stops after ~1 hour

Google Drive terminates connections after approximately 1 hour for large files. Use --continue to reuse earlier partial downloads and skip completed files. Add --retries N for up to N automatic retries per file after a transient connection failure, timeout, or incomplete transfer:

gdown --continue --retries 3 https://drive.google.com/uc?id=<file_id>
gdown --continue --retries 3 https://drive.google.com/drive/folders/<folder_id>

Retries default to zero and use exponential backoff with jitter, capped at 30 seconds. Retries resume the current transfer automatically; --continue controls whether earlier downloads are reused. Python callers can pass retries=3 to download, download_folder, or cached_download.

Retries require a filesystem destination; stdout and file-like outputs are not supported. Folder discovery and --json do not retry. If a server refuses the requested byte range, gdown stops that file and preserves the partial download. When a file exhausts its retries in a folder, remaining files are attempted and failures are reported at the end. Permission/quota errors and cancellation are not retried.

Can I use gdown for non-Google-Drive URLs?

Yes. It works with any public HTTP/HTTPS URL.

Contributing

Install just 1.58.0 or newer and uv. Recipes use Bash; on Windows, install Git for Windows and make its Bash available on PATH.

git clone https://github.com/wkentaro/gdown.git
cd gdown
just setup   # install dependencies
just test    # run tests
just lint    # run linters

License

MIT (LICENSE)

curl
download
downloader
google-drive
python
wget

wkentaro/gdown

Google Drive public file downloader when curl/wget fails.

Python

5,447

801 commits

updated Sep 29, 2026

See the code

README

gdown

PyPI Python Build License

Google Drive public file/folder downloader when curl/wget fails.

Why?

Downloading public files from Google Drive with curl or wget doesn't work — Google serves a confirmation page for large files, and the URL formats are a mess.

gdown gets around that:

  • Skips the virus-scan confirmation page so large downloads actually finish
  • Downloads folders recursively
  • Exports Google Docs/Sheets/Slides as PDF, DOCX, CSV, etc.
  • Resumes partial downloads with --continue
  • Also works with plain HTTP/HTTPS URLs as a curl/wget replacement

Install

Requires Python 3.10 or later.

pip install gdown

Or with uv:

uv tool install gdown

Quick start

# Just paste a Google Drive URL
gdown https://drive.google.com/uc?id=1l_5RK28JRL19wpT22B-DY9We3TVXnnQQ

# Or copy-paste a share link directly
gdown 'https://drive.google.com/file/d/0B9P1L--7Wd2vU3VUVlFnbTgtS2c/view?usp=sharing'

Usage

CLI

Files

# Download by URL
gdown https://drive.google.com/uc?id=1l_5RK28JRL19wpT22B-DY9We3TVXnnQQ

# Download by file ID
gdown 1l_5RK28JRL19wpT22B-DY9We3TVXnnQQ

# Download from a share link
gdown 'https://drive.google.com/file/d/0B9P1L--7Wd2vU3VUVlFnbTgtS2c/view?usp=sharing'

# Save to a specific path
gdown https://drive.google.com/uc?id=0B9P1L--7Wd2vU3VUVlFnbTgtS2c -O /tmp/spam.txt

# Resolve the filename (with its real extension) without downloading
gdown https://drive.google.com/uc?id=0B9P1L--7Wd2vU3VUVlFnbTgtS2c --json

--json is in beta and its output format may change in a future release; pass --quiet to silence the beta warning in scripts. The output is an array of {url, path} entries, where path is the filename Google Drive reports. This lets you choose a name while keeping the original extension:

url="https://drive.google.com/uc?id=0B9P1L--7Wd2vU3VUVlFnbTgtS2c"
filename=$(gdown "$url" --json | jq -r '.[0].path')
gdown "$url" -O "my_name.${filename##*.}"

Folders

# Download an entire folder
gdown https://drive.google.com/drive/folders/15uNXeRBIhVvZJIhL4yTw4IsStMhUaaxl -O /tmp/folder

# List folder contents as a JSON array (each entry has url and path)
gdown https://drive.google.com/drive/folders/15uNXeRBIhVvZJIhL4yTw4IsStMhUaaxl --json

# Filter by path and download matches
gdown https://drive.google.com/drive/folders/15uNXeRBIhVvZJIhL4yTw4IsStMhUaaxl --json \
  | jq -r '.[] | select(.path | test("shad")) | .url' \
  | xargs -n1 gdown

Folder URLs are detected automatically. A bare folder ID still requires --folder because file and folder IDs have the same format.

Google Docs, Sheets, Slides

# Download a Google Slides file (default: pptx)
gdown "https://docs.google.com/presentation/d/15umvZKlsJ3094HNg5S4vJsIhxcFlyTeK/edit?usp=sharing"

# Export as PDF instead
gdown "https://docs.google.com/presentation/d/15umvZKlsJ3094HNg5S4vJsIhxcFlyTeK/edit" --format pdf

Default export formats: Docs → docx, Sheets → xlsx, Slides → pptx.

Resume, speed limit, proxy

# Resume a partially downloaded file
gdown https://drive.google.com/uc?id=1l_5RK28JRL19wpT22B-DY9We3TVXnnQQ --continue

# Limit download speed
gdown https://drive.google.com/uc?id=1l_5RK28JRL19wpT22B-DY9We3TVXnnQQ --speed 10MB

# Download via proxy
gdown https://drive.google.com/uc?id=1l_5RK28JRL19wpT22B-DY9We3TVXnnQQ --proxy http://proxy:8080

# Give up when the server sends nothing for 30 seconds
gdown https://drive.google.com/uc?id=1l_5RK28JRL19wpT22B-DY9We3TVXnnQQ --timeout 30

Other options

# Skip TLS certificate verification
gdown https://drive.google.com/uc?id=1l_5RK28JRL19wpT22B-DY9We3TVXnnQQ --no-check-certificate

# Download as your signed-in Google account, reusing your browser's cookies
gdown https://drive.google.com/uc?id=1l_5RK28JRL19wpT22B-DY9We3TVXnnQQ --cookies-from-browser firefox

# Read and save cookies in a file other than ~/.cache/gdown/cookies.txt
gdown https://drive.google.com/uc?id=1l_5RK28JRL19wpT22B-DY9We3TVXnnQQ --cookies ./cookies.txt

# Don't read or save cookies
gdown https://drive.google.com/uc?id=1l_5RK28JRL19wpT22B-DY9We3TVXnnQQ --no-cookies

# Use a custom User-Agent
gdown https://drive.google.com/uc?id=1l_5RK28JRL19wpT22B-DY9We3TVXnnQQ --user-agent "MyApp/1.0"

Pipe to stdout

gdown https://github.com/wkentaro/gdown/archive/refs/tags/v4.0.0.tar.gz -O - --quiet | tar zxvf -

Any URL

gdown also works with regular URLs, not just Google Drive:

gdown https://httpbin.org/ip -O ip.json

[!NOTE] For Google Drive URLs, gdown automatically extracts the file ID and downloads the actual file. Use curl or wget to download the raw HTML page instead.

Python

import gdown

# Download a file
url = "https://drive.google.com/uc?id=1l_5RK28JRL19wpT22B-DY9We3TVXnnQQ"
gdown.download(url=url, output="fcn8s_from_caffe.npz")

# Download by file ID
gdown.download(id="0B9P1L--7Wd2vNm9zMTJWOGxobkU", output="output.npz")

# Download from a share link
url = "https://drive.google.com/file/d/0B9P1L--7Wd2vNm9zMTJWOGxobkU/view?usp=sharing"
gdown.download(url=url, output="output.npz")

# Download with hash verification and caching
gdown.cached_download(
    url=url,
    path="output.npz",
    hash="md5:fa837a88f0c40c513d975104edf3da17",
    postprocess=gdown.extractall,
)

# Track download progress
def on_progress(bytes_so_far: int, bytes_total: int | None) -> None:
    if bytes_total is not None:
        print(f"\r{bytes_so_far / bytes_total * 100:.1f}%", end="")

gdown.download(url=url, output="output.npz", quiet=True, progress=on_progress)

# Download a folder
url = "https://drive.google.com/drive/folders/15uNXeRBIhVvZJIhL4yTw4IsStMhUaaxl"
gdown.download_folder(url=url)

# Download a folder by ID
gdown.download_folder(id="15uNXeRBIhVvZJIhL4yTw4IsStMhUaaxl")

FAQ

"Permission Denied" error

Make sure the file sharing is set to "Anyone with the link".

Google throttles downloads when too many people access the same file, but lets a signed-in account through. If you can still open the file in your browser, reuse that browser's cookies:

gdown --cookies-from-browser firefox https://drive.google.com/uc?id=FILE_ID

Supported browsers: brave, chrome, chromium, edge, firefox, opera, safari, vivaldi, whale. gdown saves the cookies to ~/.cache/gdown/cookies.txt, so later runs need no flag. That file then holds your whole google.com session, Gmail and Account included, so treat it like a password. To revoke it, delete the file and sign out of Google in that browser.

Platform notes:

  • Linux Chromium-family browsers using GNOME Keyring require secretstorage in gdown's Python environment. Install with pip install 'gdown[secretstorage]' or run uvx --from 'gdown[secretstorage]' gdown --cookies-from-browser chrome URL. Firefox needs no extra dependency.
  • macOS asks for your login password once to unlock the Chromium-family keychain entry; Firefox needs nothing.
  • Windows Chrome 127+ encrypts cookies so other programs cannot read them. Use Firefox there.
  • Safari requires Full Disk Access for your terminal.

If none of that works, export a Netscape cookies.txt with a browser extension such as Get cookies.txt LOCALLY and pass it with --cookies cookies.txt. gdown rewrites that file while resolving each Google Drive file, whether or not it downloads it.

Download stops after ~1 hour

Google Drive terminates connections after approximately 1 hour for large files. Use --continue to reuse earlier partial downloads and skip completed files. Add --retries N for up to N automatic retries per file after a transient connection failure, timeout, or incomplete transfer:

gdown --continue --retries 3 https://drive.google.com/uc?id=<file_id>
gdown --continue --retries 3 https://drive.google.com/drive/folders/<folder_id>

Retries default to zero and use exponential backoff with jitter, capped at 30 seconds. Retries resume the current transfer automatically; --continue controls whether earlier downloads are reused. Python callers can pass retries=3 to download, download_folder, or cached_download.

Retries require a filesystem destination; stdout and file-like outputs are not supported. Folder discovery and --json do not retry. If a server refuses the requested byte range, gdown stops that file and preserves the partial download. When a file exhausts its retries in a folder, remaining files are attempted and failures are reported at the end. Permission/quota errors and cancellation are not retried.

Can I use gdown for non-Google-Drive URLs?

Yes. It works with any public HTTP/HTTPS URL.

Contributing

Install just 1.58.0 or newer and uv. Recipes use Bash; on Windows, install Git for Windows and make its Bash available on PATH.

git clone https://github.com/wkentaro/gdown.git
cd gdown
just setup   # install dependencies
just test    # run tests
just lint    # run linters

License

MIT (LICENSE)

curl
download
downloader
google-drive
python
wget

Significant stargazers

Albert Villanova del Moral

622 followers · starred Dec 2021

Marco Edward Gorelli

687 followers · starred Jan 2023

Jonas Haag

422 followers · starred May 2020

fatih akyon

780 followers · starred Apr 2026