Use when capturing screenshots of local projects, documenting web app UI, taking screenshots of localhost dev servers, or generating images for READMEs and docs. Use when asked to "screenshot my app", "capture the UI", "take a screenshot of localhost", "generate screenshots for docs", "batch screenshot my pages", or "set up shot-scraper".
Resources
1Install
npx skillscat add antjanus/skillbox/screenshot-local Install via the SkillsCat registry.
Screenshot Local - Capture Project Screenshots with shot-scraper
Overview
Capture screenshots of local development projects using shot-scraper installed globally via pipx. Turn localhost URLs and local HTML files into PNGs, JPEGs, and PDFs for documentation, READMEs, and design reviews.
Core principle: Screenshots should be reproducible from a single command or YAML config, not manual screen captures. Version-control your screenshot configs alongside your code.
When to Use
Use this skill when:
- Capturing screenshots of a local dev server for docs or README
- Generating screenshots of multiple pages/states in batch
- Documenting UI changes or new features visually
- Creating before/after comparisons during refactoring
- Automating screenshot generation in CI/CD
Avoid when:
- Recording terminal/CLI output (use
record-tuiwith VHS instead) - Capturing non-web content (use native screenshot tools)
- Scraping third-party websites (shot-scraper can do it, but this skill focuses on local projects)
Prerequisites
Install shot-scraper globally via pipx:
# Install pipx if needed
brew install pipx # macOS
# or: apt install pipx / pip install pipx
# Install shot-scraper globally
pipx install shot-scraper
# Install the browser engine (Chromium by default)
shot-scraper installVerify: shot-scraper --version
Alternative browsers:
shot-scraper install -b firefox
shot-scraper install -b webkitPhase 1: Plan the Screenshots
Before capturing, answer these questions:
- What are you capturing? — localhost URL, local HTML file, or built static site
- Which pages/states? — Single page, multiple routes, or specific UI states
- What dimensions? — Match your target display context
- Any interaction needed? — Click buttons, fill forms, dismiss modals before capture
Recommended dimensions by use case:
| Use Case | Width | Height | Format |
|---|---|---|---|
| README hero image | 1280 | 800 | PNG |
| Docs screenshot | 1200 | auto | PNG |
| Social/OG image | 1200 | 630 | PNG |
| Mobile viewport | 375 | 812 | PNG |
| Tablet viewport | 768 | 1024 | PNG |
| Full page capture | 1280 | (omit) | PNG |
Phase 2: Capture Screenshots
Single Screenshot
Capture a localhost page:
shot-scraper http://localhost:3000 -o homepage.pngCapture a local HTML file:
shot-scraper index.html -o preview.pngWith custom dimensions:
shot-scraper http://localhost:3000 -w 1200 -h 800 -o homepage.pngRetina (2x resolution):
shot-scraper http://localhost:3000 --retina -o homepage-retina.pngCapture a specific element:
shot-scraper http://localhost:3000 -s ".hero-section" -o hero.png
shot-scraper http://localhost:3000 -s "#main-nav" --padding 10 -o nav.pngWait for dynamic content:
# Wait fixed time (ms)
shot-scraper http://localhost:3000 --wait 2000 -o page.png
# Wait for JS condition
shot-scraper http://localhost:3000 --wait-for "document.querySelector('.loaded')" -o page.pngExecute JS before capture (dismiss modals, set state):
shot-scraper http://localhost:3000 \
-j "document.querySelector('.cookie-banner')?.remove()" \
-o clean-homepage.pngEssential Options
| Flag | Example | Purpose |
|---|---|---|
-o |
-o hero.png |
Output filename |
-w |
-w 1280 |
Viewport width (default: 1280) |
-h |
-h 800 |
Viewport height (omit for full page) |
-s |
-s ".card" |
CSS selector to capture |
--selector-all |
--selector-all ".card" |
All matching elements |
-p |
-p 10 |
Padding around selector (px) |
--retina |
--retina |
2x device pixel ratio |
--quality |
--quality 80 |
Save as JPEG with quality |
--wait |
--wait 2000 |
Wait ms after page load |
--wait-for |
--wait-for "expr" |
Wait until JS returns true |
-j |
-j "js code" |
Execute JS before screenshot |
-b |
-b firefox |
Browser (chromium/firefox/webkit) |
--omit-background |
--omit-background |
Transparent background (PNG) |
--timeout |
--timeout 10000 |
Failure timeout (ms) |
For the complete flag reference, see Command Reference.
Batch Screenshots with YAML
Create a shots.yml for capturing multiple pages:
# shots.yml
- url: http://localhost:3000
output: screenshots/homepage.png
width: 1280
height: 800
- url: http://localhost:3000/about
output: screenshots/about.png
width: 1280
- url: http://localhost:3000/dashboard
output: screenshots/dashboard.png
width: 1280
height: 900
wait: 2000
javascript: |
document.querySelector('.loading-spinner')?.remove()
- url: http://localhost:3000
output: screenshots/mobile-home.png
width: 375
height: 812Run the batch:
shot-scraper multi shots.ymlAdvanced YAML Keys
- url: http://localhost:3000/form
output: screenshots/form-filled.png
width: 1200
javascript: |
document.querySelector('#name').value = 'Jane Doe';
document.querySelector('#email').value = 'jane@example.com';
wait: 500
selector: ".form-container"
padding: 20
retina: trueSupported YAML keys: url, output, width, height, quality, wait, wait_for, selector, selectors, selector_all, padding, javascript, js_selector, retina, omit_background
Phase 3: Smart Config Generation
When asked to generate a screenshot config for a project, follow this process:
Step 1: Analyze the Project
Read the project to understand:
- Routes/pages — Check router config, page files, or navigation
- Key UI states — Loading, empty, populated, error states
- Important components — Hero sections, dashboards, forms
- Port — What port does the dev server run on
Step 2: Generate shots.yml
Build a YAML config covering the project's key screens:
# Validate by running
shot-scraper multi shots.ymlStep 3: Iterate
Review screenshots, adjust timing and selectors, re-run.
Phase 4: Optimize Output
File Size Reduction
Use JPEG for photos/complex UIs:
shot-scraper http://localhost:3000 --quality 85 -o page.jpgUse PNG for UI with text/sharp edges (default).
Transparent backgrounds (for overlaying on docs):
shot-scraper http://localhost:3000 -s ".component" --omit-background -o widget.pngConsistency Tips
- Always set explicit
width— default 1280 is fine but be intentional - Omit
heightfor full-page captures, set it for fixed viewport - Use
--retinafor README images viewed on high-DPI screens - Add
--waitfor SPAs that hydrate client-side - Use
javascriptto dismiss cookie banners, tooltips, or modals - Use
selector+paddingto capture specific components cleanly
Phase 5: CI/CD Integration
GitHub Actions
name: Update Screenshots
on:
push:
branches: [main]
paths: ["src/**", "shots.yml"]
jobs:
screenshots:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Setup Python
uses: actions/setup-python@v5
with:
python-version: "3.12"
- name: Install shot-scraper
run: |
pip install shot-scraper
shot-scraper install
- name: Capture screenshots
run: |
npm ci && npm run dev &
sleep 5
shot-scraper multi shots.yml
- name: Commit updated screenshots
uses: stefanzweifel/git-auto-commit-action@v5
with:
commit_message: "docs: update screenshots"
file_pattern: "screenshots/*.png"Tip: Use the server key in YAML to auto-start a dev server — see Templates.
Examples
Good: Well-Structured Screenshot Config
# shots.yml — explicit dimensions, proper waits, organized output
- url: http://localhost:3000
output: screenshots/homepage.png
width: 1280
height: 800
- url: http://localhost:3000/dashboard
output: screenshots/dashboard.png
width: 1280
height: 900
wait: 2000
javascript: |
document.querySelector('.toast-notification')?.remove()
- url: http://localhost:3000/settings
output: screenshots/settings.png
width: 1280
selector: ".settings-panel"
padding: 20
- url: http://localhost:3000
output: screenshots/mobile-home.png
width: 375
height: 812
Bad: Common Mistakes
# No output specified — shot-scraper auto-names from URL, messy results
- url: http://localhost:3000
# No width — relies on default, inconsistent across machines
- url: http://localhost:3000/about
output: about.png
# No wait for SPA — captures loading spinner instead of content
- url: http://localhost:3000/dashboard
output: dashboard.png
# Screenshot directory not organized
- url: http://localhost:3000/settings
output: settings.png
Good: Capturing Specific Components
# Hero section with padding for breathing room
shot-scraper http://localhost:3000 -s ".hero" -p 20 -o docs/hero.png
# Navigation in retina for crisp text
shot-scraper http://localhost:3000 -s "nav" --retina -o docs/nav.png
# Form with pre-filled data via JS
shot-scraper http://localhost:3000/contact \
-j "document.querySelector('#name').value = 'Jane Doe'" \
-s ".contact-form" -p 10 -o docs/form.png
Bad: Component Capture Anti-Patterns
# No selector — captures entire page when you only need one section
shot-scraper http://localhost:3000 -o hero.png
# No padding — element cropped tight, looks cramped in docs
shot-scraper http://localhost:3000 -s ".hero" -o hero.png
# No wait — dynamic component hasn't rendered yet
shot-scraper http://localhost:3000 -s ".chart" -o chart.png
Troubleshooting
Problem: Screenshot shows blank page or loading spinner
Cause: SPA hasn't hydrated or async data hasn't loaded.
Solution:
# Fixed wait
shot-scraper http://localhost:3000 --wait 3000 -o page.png
# Wait for specific element
shot-scraper http://localhost:3000 --wait-for "document.querySelector('.content')" -o page.pngProblem: "Connection refused" on localhost
Cause: Dev server isn't running or is on a different port.
Solution:
- Start your dev server first:
npm run dev & - Verify the port:
curl -I http://localhost:3000 - Or use the
serverkey in YAML to auto-start it
Problem: Screenshot dimensions don't match expectations
Cause: Height omitted (captures full page) or retina not accounted for.
Solution:
- Set explicit
-hfor fixed viewport - Omit
-hintentionally for full-page capture --retinadoubles pixel dimensions (1280w becomes 2560px image)
Problem: shot-scraper command not found
Cause: Not installed or pipx PATH not configured.
Solution:
pipx install shot-scraper
pipx ensurepath # Add pipx bin to PATH
shot-scraper install # Install browser engineProblem: Elements missing from screenshot
Cause: CSS selector wrong, element behind a modal, or lazy-loaded content.
Solution:
# Use --interactive to debug visually
shot-scraper http://localhost:3000 -i
# Use --devtools for inspector
shot-scraper http://localhost:3000 --devtoolsIntegration
This skill pairs with:
- record-tui — For terminal app recordings (use VHS for CLIs, shot-scraper for web UIs)
- track-session — Track screenshot iteration progress
- git-worktree — Compare screenshots across branches
Useful alongside:
- shot-scraper — The screenshot tool
- shot-scraper-template — GitHub Actions template
- pipx — Global Python app installer
Quick Reference
# Single screenshot
shot-scraper http://localhost:3000 -o page.png
# With dimensions
shot-scraper http://localhost:3000 -w 1280 -h 800 -o page.png
# Specific element
shot-scraper http://localhost:3000 -s ".hero" -p 10 -o hero.png
# Retina
shot-scraper http://localhost:3000 --retina -o page@2x.png
# Local HTML file
shot-scraper index.html -o preview.png
# Batch from YAML
shot-scraper multi shots.yml
# Interactive debugging
shot-scraper http://localhost:3000 -i
# PDF export
shot-scraper pdf http://localhost:3000 -o page.pdfDeep Reference
For detailed guides, load these files when needed:
- Command Reference — All shot-scraper commands, flags, and subcommands
- Templates — Copy-paste YAML configs for common project types
Only load these when specifically needed to save context.
References
- shot-scraper — Official repository
- shot-scraper documentation — Full docs
- shot-scraper-template — GitHub Actions template
- pipx — Global Python app installer
- Simon Willison's blog — Author's posts on shot-scraper