docsend-dl
Save any public Dropbox DocSend deck as a PDF — one command, full quality.
Quickstart
pip install docsend-dl && playwright install chromium
docsend-dl https://docsend.com/view/XXXXXX
That's it. You'll get a PDF named after the deck in your current directory.
Demo
$ docsend-dl https://dbx.docsend.com/view/n43v89r
Found deck: "docsend-n43v89r" (21 slides)
Got 21/21 image URLs
Downloading slides ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 21/21 0:00:00
╭──────────────────────── Done in 32.2s ─────────────────────────╮
│ Slides saved: 21/21 │
│ PDF size: 9.5 MB │
│ Output: /home/user/docsend-n43v89r.pdf │
╰────────────────────────────────────────────────────────────────╯
Features
- PDF by default — slides are assembled into a single PDF at full resolution with no re-encoding
- PNG export — pass
--imagesto save individual slide images instead - Smart output paths — pass a
.pdffilename, a directory, or let it default to{deck title}.pdf - Fast — downloads all slides in parallel with automatic retries
- Works with both
docsend.comanddbx.docsend.comURLs - Headless — runs in the background by default; use
--no-headlessto watch the browser
Installation
You need the package itself plus a Chromium browser for Playwright:
pip install docsend-dl
playwright install chromium
Or if you use uv:
uv tool install docsend-dl
uv run playwright install chromium
Usage
CLI
# Download as PDF (default)
docsend-dl https://docsend.com/view/XXXXXX
# Save PDF to a specific path
docsend-dl https://docsend.com/view/XXXXXX --output "My Deck.pdf"
# Save PDF into a directory (uses deck title as filename)
docsend-dl https://docsend.com/view/XXXXXX --output ./downloads
# Download as individual PNG images instead
docsend-dl https://docsend.com/view/XXXXXX --images
# Show the browser window during download
docsend-dl https://dbx.docsend.com/view/XXXXXX --no-headless
Python API
import asyncio
from docsend_dl import download_deck
# Download as PDF (default)
result = asyncio.run(download_deck(
url="https://docsend.com/view/XXXXXX",
))
print(f"Saved PDF to {result.output_path} ({result.total_bytes} bytes)")
# Download as individual images
result = asyncio.run(download_deck(
url="https://docsend.com/view/XXXXXX",
output="My Deck",
images_only=True,
))
print(f"Saved {result.successes}/{result.slide_count} slides")
For finer control you can call the extraction and download steps separately:
import asyncio
from pathlib import Path
from docsend_dl import extract_slide_urls, download_slides
async def main():
deck_info = await extract_slide_urls(url="https://docsend.com/view/XXXXXX")
result = await download_slides(
urls=deck_info.image_urls,
output_dir=Path("slides"),
)
print(f"Downloaded {result.successes} slides")
asyncio.run(main())
How It Works
- Opens the DocSend page in a headless Chromium browser (via Playwright)
- Extracts each slide's image URL from the page data
- Downloads all slide images in parallel (via httpx)
- Assembles the images into a single PDF (via img2pdf) or saves them as PNGs
Limitations
- Only works with public decks — email-gated and passcode-protected decks are not supported
- Requires Chromium to be installed via
playwright install chromium
Contributing
# Clone and install dev dependencies
git clone https://github.com/captivus/docsend-dl.git
cd docsend-dl
uv sync
# Run unit tests (fast, no network needed)
uv run pytest -m "not integration"
# Run integration tests (downloads real decks, verifies checksums)
uv run pytest tests/test_integration.py
# Run everything
uv run pytest
Bug reports and pull requests are welcome on GitHub.
License
Metadata
Release files for docsend-dl 0.1.2
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | Provenance | |
|---|---|---|---|---|
| docsend_dl-0.1.2.tar.gz | 10.2 kB | Without provenance | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| docsend_dl-0.1.2-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 23.6 kB
Release files / docsend_dl-0.1.2.tar.gz
| Download URL | docsend_dl-0.1.2.tar.gz |
|---|---|
| Size | 10.2 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
ee9800d8765316f5cfac40b87dc3d74f366293f70d1bb900a368185f6ed39654
|
|
BLAKE2b-256 checksum How to use checksums |
e92c4db40c58b71591ab1761dd85a18dfd70fb16aaa4106d36dba3de73068bdd
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
uv/0.11.6 {"installer":{"name":"uv","version":"0.11.6","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}
|
Release files / docsend_dl-0.1.2-py3-none-any.whl
| Download URL | docsend_dl-0.1.2-py3-none-any.whl |
|---|---|
| Size | 13.5 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
808d7dbc549c331052a8b8670a2df84dfc25a3202bda27974c64f8dfbdd791b9
|
|
BLAKE2b-256 checksum How to use checksums |
cf4b089e373854525d03bb06d404b1f395baf486a770502acd892d7ec2d900b8
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
uv/0.11.6 {"installer":{"name":"uv","version":"0.11.6","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}
|
Security for docsend-dl 0.1.2
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
No provenance found
None of the files in this release were uploaded with provenance metadata.
A note on package security
PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.
To learn more about protecting yourself from malicious actors, visit our package security documentation.