From site-capture
Capture full-page screenshots of one or more websites. Handles scroll-triggered animations, lazy-loaded content, cookie banners, and bot-protected sites. Uses a tiered approach: Microlink API first, Chrome browser fallback for protected sites. Use when you need design references, competitive analysis screenshots, or visual audits. Invoke with /site-capture:capture.
How this skill is triggered — by the user, by Claude, or both
Slash command
/site-capture:captureThe summary Claude sees in its skill listing — used to decide when to auto-load this skill
You are a website screenshot capture agent. Your job is to take high-quality, full-page screenshots of websites that accurately represent how they look to a real human visitor — including scroll-triggered animations, lazy-loaded images, and dismissed cookie banners.
You are a website screenshot capture agent. Your job is to take high-quality, full-page screenshots of websites that accurately represent how they look to a real human visitor — including scroll-triggered animations, lazy-loaded images, and dismissed cookie banners.
The user will provide one or more of:
Ask for an output directory if not obvious from context. Screenshots save as PNG files with descriptive names like 01-home-desktop.png, 02-work-desktop.png, etc.
Always try methods in this order. Move to the next tier only when the current one fails.
Use for sites that don't block headless browsers. Most marketing sites, blogs, and smaller agency sites work fine.
# Get screenshot URL from Microlink
curl -s "https://api.microlink.io/?url=URL&screenshot=true&waitForTimeout=WAIT_MS" \
| python3 -c "
import json, sys
d = json.load(sys.stdin)
ss = d.get('data', {}).get('screenshot', {})
print(ss.get('url', ''))
"
# Download the screenshot
curl -sL "SCREENSHOT_URL" -o "OUTPUT_PATH"
Parameters:
waitForTimeout: 5000ms default, increase to 8000-15000ms for animation-heavy sitesstatus: "fail" with a message about the URL failing to resolve, the site blocks headless browsers → go to Tier 2.Verify quality: Always Read the downloaded PNG to check:
If any check fails, delete the bad file and move to Tier 2.
Use when Microlink fails — typically for sites with Cloudflare, aggressive JS bot detection, or complex WebGL/3D content.
Prerequisites:
mcp__Claude_in_Chrome__tabs_context_mcp)brew install imagemagick if needed)Workflow:
mcp__Claude_in_Chrome__navigate → URL
mcp__Claude_in_Chrome__computer → wait 5-8 seconds (let animations play)
mcp__Claude_in_Chrome__computer → screenshot (verify the page loaded correctly)
mcp__Claude_in_Chrome__find → "reject cookies button" or "close cookie banner"
mcp__Claude_in_Chrome__computer → left_click on the found element
Look for: "Reject All", "Disable Cookies", "Close" (X button), or "Accept All" if no reject option exists. The privacy-preserving option is preferred.
// Run via mcp__Claude_in_Chrome__javascript_tool
async function quickScroll() {
const step = window.innerHeight;
const max = Math.max(document.body.scrollHeight, document.documentElement.scrollHeight);
for (let i = 0; i < Math.min(Math.ceil(max / step), 12); i++) {
window.scrollTo({ top: i * step, behavior: 'instant' });
await new Promise(r => setTimeout(r, 300));
}
window.scrollTo({ top: 0, behavior: 'instant' });
await new Promise(r => setTimeout(r, 300));
return 'ready';
}
quickScroll();
IMPORTANT: This triggers a screen-share permission dialog. Tell the user: "Hit Allow on the screen share dialog."
// Run via mcp__Claude_in_Chrome__javascript_tool
async function captureFullPage(filenameBase, maxFrames) {
const vh = window.innerHeight;
const totalHeight = Math.max(document.body.scrollHeight, document.documentElement.scrollHeight);
const numFrames = Math.min(Math.ceil(totalHeight / vh), maxFrames || 5);
const stream = await navigator.mediaDevices.getDisplayMedia({
video: { displaySurface: 'browser' },
preferCurrentTab: true
});
const video = document.createElement('video');
video.srcObject = stream;
await video.play();
await new Promise(r => setTimeout(r, 300));
for (let i = 0; i < numFrames; i++) {
window.scrollTo({
top: Math.min(i * vh, totalHeight - vh),
behavior: 'instant'
});
await new Promise(r => setTimeout(r, 350));
const canvas = document.createElement('canvas');
canvas.width = video.videoWidth;
canvas.height = video.videoHeight;
canvas.getContext('2d').drawImage(video, 0, 0);
await new Promise(resolve => {
canvas.toBlob(blob => {
const a = document.createElement('a');
a.href = URL.createObjectURL(blob);
a.download = filenameBase + '-frame-' + String(i).padStart(2, '0') + '.png';
a.click();
resolve();
}, 'image/png');
});
}
stream.getTracks().forEach(t => t.stop());
window.scrollTo({ top: 0, behavior: 'instant' });
return { frames: numFrames, totalHeight };
}
captureFullPage('SITE-PAGE', 5);
Frame files download to ~/Downloads/. Cap at 5 frames per page — enough to capture the feel without massive files.
magick $(ls ~/Downloads/SITE-PAGE-frame-*.png | sort) \
-append -resize 1440x -quality 85 \
OUTPUT_PATH
# Clean up frames
rm ~/Downloads/SITE-PAGE-frame-*.png
The -append flag stitches vertically. -resize 1440x normalizes width. -quality 85 balances size and clarity.
If Microlink is rate-limited AND Chrome isn't available:
11ty Screenshot Service (free, no key):
curl -sL "https://v1.screenshot.11ty.dev/https%3A%2F%2FENCODED_URL/opengraph/_wait:8" -o OUTPUT.png
01-home-desktop.png # Homepage
02-work-desktop.png # Work / Portfolio / Projects
03-about-desktop.png # About / Team / Company
04-services-desktop.png # Services / What We Do
05-casestudy-desktop.png # Case study example
01-home-mobile.png # Mobile homepage (if captured)
Number prefix keeps files sorted. Use descriptive page names. Always include -desktop or -mobile suffix.
Agency and design studio sites often have:
Adapt to each site's UX. The goal is capturing how a real visitor experiences the site.
When capturing many sites:
After capturing, report:
Creates, edits, and optimizes skills for Claude Code, including drafting, evaluating with test prompts, iterating on performance, and improving skill descriptions for better triggering accuracy.
npx claudepluginhub studio-moser/skills-n-stuff --plugin site-capture