[{"data":1,"prerenderedAt":352},["ShallowReactive",2],{"blog-\u002Fblog\u002Freal-screenshots-headless-capture":3},{"id":4,"title":5,"body":6,"date":343,"description":344,"draft":345,"extension":346,"meta":347,"navigation":63,"path":348,"seo":349,"stem":350,"__hash__":351},"blog\u002Fblog\u002Freal-screenshots-headless-capture.md","Real screenshots, not stock slop — headless source-page capture",{"type":7,"value":8,"toc":338},"minimark",[9,13,21,26,29,240,244,247,290,293,297,300,319,322,334],[10,11,12],"p",{},"Nothing says \"low-effort content\" like generic stock B-roll laid over a tech story. Glowing\nblue circuit boards, a stock-footage hacker in a hoodie. The moment it appears, the viewer\nknows nobody read the source.",[10,14,15,16,20],{},"The fix is nearly free: ",[17,18,19],"strong",{},"show the actual thing."," The GitHub repo. The docs page. The\nrelease notes. The benchmark table from the paper. A headless browser makes that cheap enough\nto do every single time.",[22,23,25],"h2",{"id":24},"the-capture","The capture",[10,27,28],{},"Playwright drives a real Chromium, navigates to the source, and screenshots it:",[30,31,36],"pre",{"className":32,"code":33,"language":34,"meta":35,"style":35},"language-python shiki shiki-themes github-dark github-dark","from playwright.sync_api import sync_playwright\n\ndef capture(url: str, out: str, width=1280, height=1600):\n    with sync_playwright() as p:\n        browser = p.chromium.launch()\n        page = browser.new_page(\n            viewport={\"width\": width, \"height\": height},\n            device_scale_factor=2,  # retina-crisp — non-negotiable for video\n        )\n        page.goto(url, wait_until=\"networkidle\")\n        page.screenshot(path=out, full_page=False)\n        browser.close()\n","python","",[37,38,39,58,65,107,122,133,144,169,187,193,210,234],"code",{"__ignoreMap":35},[40,41,44,48,52,55],"span",{"class":42,"line":43},"line",1,[40,45,47],{"class":46},"sOPea","from",[40,49,51],{"class":50},"suv1-"," playwright.sync_api ",[40,53,54],{"class":46},"import",[40,56,57],{"class":50}," sync_playwright\n",[40,59,61],{"class":42,"line":60},2,[40,62,64],{"emptyLinePlaceholder":63},true,"\n",[40,66,68,71,75,78,82,85,87,90,93,96,99,101,104],{"class":42,"line":67},3,[40,69,70],{"class":46},"def",[40,72,74],{"class":73},"sFR8T"," capture",[40,76,77],{"class":50},"(url: ",[40,79,81],{"class":80},"s8ozJ","str",[40,83,84],{"class":50},", out: ",[40,86,81],{"class":80},[40,88,89],{"class":50},", width",[40,91,92],{"class":46},"=",[40,94,95],{"class":80},"1280",[40,97,98],{"class":50},", height",[40,100,92],{"class":46},[40,102,103],{"class":80},"1600",[40,105,106],{"class":50},"):\n",[40,108,110,113,116,119],{"class":42,"line":109},4,[40,111,112],{"class":46},"    with",[40,114,115],{"class":50}," sync_playwright() ",[40,117,118],{"class":46},"as",[40,120,121],{"class":50}," p:\n",[40,123,125,128,130],{"class":42,"line":124},5,[40,126,127],{"class":50},"        browser ",[40,129,92],{"class":46},[40,131,132],{"class":50}," p.chromium.launch()\n",[40,134,136,139,141],{"class":42,"line":135},6,[40,137,138],{"class":50},"        page ",[40,140,92],{"class":46},[40,142,143],{"class":50}," browser.new_page(\n",[40,145,147,151,153,156,160,163,166],{"class":42,"line":146},7,[40,148,150],{"class":149},"s-3mD","            viewport",[40,152,92],{"class":46},[40,154,155],{"class":50},"{",[40,157,159],{"class":158},"s4wv1","\"width\"",[40,161,162],{"class":50},": width, ",[40,164,165],{"class":158},"\"height\"",[40,167,168],{"class":50},": height},\n",[40,170,172,175,177,180,183],{"class":42,"line":171},8,[40,173,174],{"class":149},"            device_scale_factor",[40,176,92],{"class":46},[40,178,179],{"class":80},"2",[40,181,182],{"class":50},",  ",[40,184,186],{"class":185},"sJ8bj","# retina-crisp — non-negotiable for video\n",[40,188,190],{"class":42,"line":189},9,[40,191,192],{"class":50},"        )\n",[40,194,196,199,202,204,207],{"class":42,"line":195},10,[40,197,198],{"class":50},"        page.goto(url, ",[40,200,201],{"class":149},"wait_until",[40,203,92],{"class":46},[40,205,206],{"class":158},"\"networkidle\"",[40,208,209],{"class":50},")\n",[40,211,213,216,219,221,224,227,229,232],{"class":42,"line":212},11,[40,214,215],{"class":50},"        page.screenshot(",[40,217,218],{"class":149},"path",[40,220,92],{"class":46},[40,222,223],{"class":50},"out, ",[40,225,226],{"class":149},"full_page",[40,228,92],{"class":46},[40,230,231],{"class":80},"False",[40,233,209],{"class":50},[40,235,237],{"class":42,"line":236},12,[40,238,239],{"class":50},"        browser.close()\n",[22,241,243],{"id":242},"the-touches-that-separate-it-from-a-scrape","The touches that separate it from a scrape",[10,245,246],{},"A raw screenshot still looks scraped. Four things make it look intentional:",[248,249,250,260,270,280],"ul",{},[251,252,253,259],"li",{},[17,254,255,258],{},[37,256,257],{},"device_scale_factor=2","."," Capture at 2x and your screenshots are crisp when a video\nscales them up. A blurry screenshot is worse than no screenshot.",[251,261,262,265,266,269],{},[17,263,264],{},"Wait for the real content."," ",[37,267,268],{},"wait_until=\"networkidle\""," — or better, wait for a specific\nselector — so you don't capture a half-loaded skeleton.",[251,271,272,275,276,279],{},[17,273,274],{},"Kill the cookie banners."," A GDPR overlay in your shot screams \"I scraped this.\" Inject\nCSS to hide ",[37,277,278],{},"[id*=\"cookie\"], [class*=\"consent\"]",", or click the dismiss button before you\nshoot.",[251,281,282,285,286,289],{},[17,283,284],{},"Crop to what matters."," Don't screenshot the whole page and zoom in post. Grab the\nelement: ",[37,287,288],{},"page.locator(\"table.benchmarks\").screenshot(path=out)",". Frame the diff, the\ntable, the one paragraph you're talking about.",[10,291,292],{},"Then, in the video, a slow sub-pixel zoom across the screenshot (a Ken Burns move) reads as\ndeliberate instead of a static slide.",[22,294,296],{"id":295},"be-a-good-citizen","Be a good citizen",[10,298,299],{},"Headless capture is scraping, so behave like it:",[248,301,302,309,316],{},[251,303,304,305,308],{},"Set a real ",[37,306,307],{},"user_agent"," and don't hammer — you're grabbing one image, not crawling a site.",[251,310,311,312,315],{},"Respect ",[37,313,314],{},"robots.txt"," and terms of service. Public docs and repos are fair game; gated or\nauth-walled content is not.",[251,317,318],{},"Cache captures. The same release-notes page doesn't need re-shooting every run.",[320,321],"hr",{},[10,323,324,325,329,330,333],{},"The difference between content that looks ",[326,327,328],"em",{},"researched"," and content that looks ",[326,331,332],{},"generated"," is\noften a single question: did you show the actual source? Headless capture makes the honest\nanswer — yes — cheap enough that there's no excuse not to.",[335,336,337],"style",{},"html pre.shiki code .sOPea, html code.shiki .sOPea{--shiki-default:#F97583;--shiki-dark:#F97583}html pre.shiki code .suv1-, html code.shiki .suv1-{--shiki-default:#E1E4E8;--shiki-dark:#E1E4E8}html pre.shiki code .sFR8T, html code.shiki .sFR8T{--shiki-default:#B392F0;--shiki-dark:#B392F0}html pre.shiki code .s8ozJ, html code.shiki .s8ozJ{--shiki-default:#79B8FF;--shiki-dark:#79B8FF}html pre.shiki code .s-3mD, html code.shiki .s-3mD{--shiki-default:#FFAB70;--shiki-dark:#FFAB70}html pre.shiki code .s4wv1, html code.shiki .s4wv1{--shiki-default:#9ECBFF;--shiki-dark:#9ECBFF}html pre.shiki code .sJ8bj, html code.shiki .sJ8bj{--shiki-default:#6A737D;--shiki-dark:#6A737D}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}",{"title":35,"searchDepth":60,"depth":60,"links":339},[340,341,342],{"id":24,"depth":60,"text":25},{"id":242,"depth":60,"text":243},{"id":295,"depth":60,"text":296},"2026-06-17","Stock footage screams content farm. Capturing the actual source — the repo, the docs, the release notes — with a headless browser makes the output look like it came from someone who read the thing.",false,"md",{},"\u002Fblog\u002Freal-screenshots-headless-capture",{"title":5,"description":344},"blog\u002Freal-screenshots-headless-capture","MPd3R8hK_7a__ZqBgR1BzWUmBuCzvieLkfDDo4iP4t8",1781756059952]