A smart desktop video scraper built with Python, PyQt6, Playwright, and yt-dlp.
VideoBot crawls listing/gallery pages, follows each item to its detail page, downloads the video, waits 5 seconds (always), then moves on — page after page until you tell it to stop.
- Dual-engine download
- yt-dlp handles YouTube, Vimeo, Twitter/X, TikTok, Dailymotion, Reddit, and 1000+ other platforms automatically
- Playwright direct extraction falls back for sites with raw
<video>tags, MP4/WebM links, og:video meta, JSON-LD VideoObject, anddata-*attributes
- Smart two-phase crawler — JS scoring heuristic finds item page links on listing/gallery pages, same approach as ScrapeBot
- Quality selector — Best, 1080p, 720p, 480p, or Worst
- Format preference — MP4, WebM, or Any
- Respectful rate limiting — hardcoded 5-second wait after every download, never skipped
- File validation — rejects files under 100 KB
- Unlimited pagination — auto-clicks next page until max pages reached or Stop pressed
- Dark desktop UI — live stat cards, scrolling log, progress bar
- Python 3.9+
- ffmpeg (for merging video+audio tracks from YouTube etc.)
brew install ffmpeg
cd /Volumes/NVME1TB/videobot
pip install -r requirements.txt
playwright install chromiumpython run.py- Paste a listing or gallery URL into Start URL
- Works with YouTube channels/playlists, Vimeo showcases, video grid sites, etc.
- Choose a Save To folder (defaults to
~/Downloads/VideoBot) - Select Quality and Format
- Set Max Pages —
∞ Unlimitedruns until you click Stop - Click ▶ Start Scraping
| Card | What it counts |
|---|---|
| Listing Pages | Gallery/listing pages crawled |
| Items Visited | Individual item URLs followed |
| Videos Saved | Files actually downloaded |
Shows real-time progress: page URLs, item URLs, yt-dlp messages, download results, 5-second delay countdowns, and final totals.
Playwright loads the gallery page and runs a JS scoring heuristic over every <a> tag:
| Signal | Points |
|---|---|
Wraps <img> or <video> |
+6 |
| Inside a card/grid/feed container | +4 |
URL path contains /video/, /watch/, /clip/, etc. |
+3 |
URL contains ?v= |
+3 |
Has aria-label or title attribute |
+1 each |
Links scoring ≥ 4 are collected. The next-page URL is found via rel="next", class-name heuristics, and text content (Next, ›, »).
For every item URL, VideoBot tries two strategies in order:
A. yt-dlp — attempts to extract and download using the selected quality/format. Handles platform authentication cookies, HLS streams, DASH, and format merging via ffmpeg.
B. Playwright direct extraction — opens the page and scans for video sources using 6 strategies:
<video src>and<video><source src>og:video/og:video:secure_urlmeta tags- JSON-LD
VideoObjectwithcontentUrl <a href>links ending in.mp4,.webm,.mkv, etc.data-video-url,data-src,data-stream, etc.- YouTube/Vimeo
<iframe>embed URLs
After every successful download a 5-second delay is enforced before moving to the next item.
| Format | Extensions |
|---|---|
| MP4 | .mp4, .m4v |
| WebM | .webm |
| Matroska | .mkv |
| QuickTime | .mov |
| AVI | .avi |
| Flash Video | .flv |
| Windows Media | .wmv |
| MPEG | .mpeg, .mpg |
| Mobile | .3gp, .ogv |
- yt-dlp must be installed and ffmpeg must be on your PATH for best results
- Some sites require being logged in — yt-dlp supports
--cookies-from-browserfor this (add toydl_optsinscraper.py) - Private or age-gated content will require browser cookies; this is not configured by default
- VideoBot respects the 5-second rule even across page turns — it never batches or skips the delay
videobot/
├── videobot/
│ ├── __init__.py
│ ├── app.py # PyQt6 dark UI
│ ├── worker.py # QThread background worker
│ └── scraper.py # SmartVideoScraper (yt-dlp + Playwright)
├── requirements.txt
├── run.py
└── README.md
MIT