<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Ghezam Capital</title>
    <description>The latest articles on DEV Community by Ghezam Capital (@ghezam_capital_0898).</description>
    <link>https://dev.to/ghezam_capital_0898</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F4136072%2F96b80bf5-d8e1-4bba-8780-1a3c0bc32bbc.png</url>
      <title>DEV Community: Ghezam Capital</title>
      <link>https://dev.to/ghezam_capital_0898</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/ghezam_capital_0898"/>
    <language>en</language>
    <item>
      <title>Catching visual regressions between deploys with two API calls</title>
      <dc:creator>Ghezam Capital</dc:creator>
      <pubDate>Sat, 03 Oct 2026 11:54:14 +0000</pubDate>
      <link>https://dev.to/ghezam_capital_0898/catching-visual-regressions-between-deploys-with-two-api-calls-4no5</link>
      <guid>https://dev.to/ghezam_capital_0898/catching-visual-regressions-between-deploys-with-two-api-calls-4no5</guid>
      <description>&lt;p&gt;I build Screenshot Happy, so take this with that in mind. This post is about a problem I kept running into on client sites: something looks fine in code review, ships on Friday, and nobody notices the broken hero section until Monday.&lt;/p&gt;

&lt;h2&gt;
  
  
  The gap between "tests pass" and "it looks right"
&lt;/h2&gt;

&lt;p&gt;Unit and end-to-end tests tell you the logic works. They rarely tell you the page still &lt;em&gt;looks&lt;/em&gt; right: a CSS change that pushes the pricing table off-screen, a third-party script that covers the checkout button, a banner that disappears. Catching that usually means keeping your own headless Chrome somewhere, which is its own maintenance job.&lt;/p&gt;

&lt;h2&gt;
  
  
  Option 1: capture after a deploy (works on any plan)
&lt;/h2&gt;

&lt;p&gt;You can take a screenshot of the page from your CI job with one request and store it as a build artifact:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl &lt;span class="s2"&gt;"https://screenshot-api-production-ffd7.up.railway.app/screenshot?url=https://example.com&amp;amp;full_page=true"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"x-api-key: YOUR_API_KEY"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--output&lt;/span&gt; after-deploy.png
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;full_page=true&lt;/code&gt; captures the whole scrollable page (capped at 30,000 px), and &lt;code&gt;selector&lt;/code&gt; lets you capture just one element, for example the pricing table. Output can be PNG, JPEG or PDF. The request times out after 15 seconds, so it suits public pages, not slow authenticated flows.&lt;/p&gt;

&lt;h2&gt;
  
  
  Option 2: let a monitor watch the page for you
&lt;/h2&gt;

&lt;p&gt;If you want to be told when a page changes visually between deploys, create a monitor and point it at any webhook you control:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl &lt;span class="nt"&gt;-X&lt;/span&gt; POST &lt;span class="s2"&gt;"https://screenshot-api-production-ffd7.up.railway.app/monitors"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"x-api-key: YOUR_API_KEY"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"Content-Type: application/json"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-d&lt;/span&gt; &lt;span class="s1"&gt;'{
    "url": "https://example.com",
    "webhook_url": "https://your-server.com/webhook",
    "frecuencia_minutos": 360,
    "umbral_diferencia": 5
  }'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here &lt;code&gt;frecuencia_minutos&lt;/code&gt; is 360 (every 6 hours, the free plan's floor; paid plans go lower). Each check compares the new capture against the last one. If the percentage of changed pixels crosses &lt;code&gt;umbral_diferencia&lt;/code&gt;, we POST this to your webhook:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"monitor_id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"url"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"https://example.com"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"comprobado_en"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"2026-09-18T17:00:00.000Z"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"cambio_detectado"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"diferencia_porcentaje"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mf"&gt;12.4&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;From there it's yours: post to Slack, open a ticket, or trigger an n8n workflow from a webhook node. The delivery is retried up to 3 times if your endpoint doesn't return a 2xx.&lt;/p&gt;

&lt;h2&gt;
  
  
  What it doesn't do (yet)
&lt;/h2&gt;

&lt;p&gt;I'd rather you know before you build on it:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The threshold is a flat percentage of changed pixels across the whole page. A rotating ad or a live timestamp counts toward it, so noisy pages need a higher threshold.&lt;/li&gt;
&lt;li&gt;There is no selector-scoped comparison for monitors; &lt;code&gt;selector&lt;/code&gt; only scopes the capture itself.&lt;/li&gt;
&lt;li&gt;Checks run on a schedule (every 6 hours on the free plan, hourly on Starter), not the instant you deploy. For a "right after deploy" check, use option 1.&lt;/li&gt;
&lt;li&gt;Monitor checks run one at a time across the service, so the frequency is a target, not a real-time guarantee.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Pricing, in one line
&lt;/h2&gt;

&lt;p&gt;Free is €0 with 200 screenshots a month and 3 monitored pages. Starter is €9 and Growth is €29, each combining screenshots and monitoring in one payment. If you hit a limit you get a clear 429, not a surprise charge.&lt;/p&gt;

&lt;p&gt;The full parameter list and examples are in the docs: &lt;a href="https://screenshot-api-production-ffd7.up.railway.app/docs?utm_source=devto&amp;amp;utm_medium=article&amp;amp;utm_campaign=b7-visual-regression" rel="noopener noreferrer"&gt;https://screenshot-api-production-ffd7.up.railway.app/docs?utm_source=devto&amp;amp;utm_medium=article&amp;amp;utm_campaign=b7-visual-regression&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If you try it on a page where the diff is noisy, tell me which page type and I'll look at whether the threshold logic should change.&lt;/p&gt;

</description>
      <category>api</category>
      <category>webdev</category>
      <category>testing</category>
      <category>automation</category>
    </item>
    <item>
      <title>Turning a URL into a PDF (and catching when it changes) with one API call</title>
      <dc:creator>Ghezam Capital</dc:creator>
      <pubDate>Mon, 28 Sep 2026 14:39:41 +0000</pubDate>
      <link>https://dev.to/ghezam_capital_0898/turning-a-url-into-a-pdf-and-catching-when-it-changes-with-one-api-call-4k6p</link>
      <guid>https://dev.to/ghezam_capital_0898/turning-a-url-into-a-pdf-and-catching-when-it-changes-with-one-api-call-4k6p</guid>
      <description>&lt;p&gt;A lot of "URL to PDF" code starts the same way: spin up Puppeteer or Playwright, open the page, call &lt;code&gt;page.pdf()&lt;/code&gt;, hope the layout survives headless rendering. It works, until it's the one script nobody wants to touch because it depends on a specific Chromium version.&lt;/p&gt;

&lt;p&gt;I added PDF output to &lt;a href="https://screenshot-api-production-ffd7.up.railway.app" rel="noopener noreferrer"&gt;Screenshot Happy&lt;/a&gt; mostly because I kept needing it for the same reasons I needed screenshots: invoices-as-pages, saved copies of terms/pricing pages, "here's what this looked like" archiving.&lt;/p&gt;

&lt;h2&gt;
  
  
  The request
&lt;/h2&gt;

&lt;p&gt;Same endpoint as the PNG/JPEG capture, just a different &lt;code&gt;format&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl &lt;span class="nt"&gt;-G&lt;/span&gt; &lt;span class="s2"&gt;"https://screenshot-api-production-ffd7.up.railway.app/screenshot"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"x-api-key: YOUR_API_KEY"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--data-urlencode&lt;/span&gt; &lt;span class="s2"&gt;"url=https://example.com"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-d&lt;/span&gt; &lt;span class="s2"&gt;"format=pdf"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-d&lt;/span&gt; &lt;span class="s2"&gt;"full_page=true"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-o&lt;/span&gt; page.pdf
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;format=pdf&lt;/code&gt; renders the page as it actually looks on screen — not a print stylesheet. Add &lt;code&gt;full_page=true&lt;/code&gt; if you want one page sized to the whole scrollable content instead of just the viewport. It's not compatible with &lt;code&gt;selector&lt;/code&gt; (that one's PNG/JPEG only, for grabbing a single element).&lt;/p&gt;

&lt;h2&gt;
  
  
  The other half: knowing when the page changes
&lt;/h2&gt;

&lt;p&gt;Capturing a page once is easy. The harder question is usually "did this change since last time, and do I need to know about it?" That's what &lt;code&gt;/monitors&lt;/code&gt; is for — same capture engine, running on a schedule:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl &lt;span class="nt"&gt;-X&lt;/span&gt; POST &lt;span class="s2"&gt;"https://screenshot-api-production-ffd7.up.railway.app/monitors"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"x-api-key: YOUR_API_KEY"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"Content-Type: application/json"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-d&lt;/span&gt; &lt;span class="s1"&gt;'{
    "url": "https://example.com/pricing",
    "webhook_url": "https://your-server.com/webhook",
    "frecuencia_minutos": 60,
    "umbral_diferencia": 5
  }'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It screenshots the URL on that interval, diffs the new capture against the last one, and POSTs to your webhook only when the difference crosses the threshold (&lt;code&gt;umbral_diferencia&lt;/code&gt;, percent of changed pixels). No polling loop to write, no image-diffing library to pick and maintain.&lt;/p&gt;

&lt;h2&gt;
  
  
  Where this is actually useful
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;QA / visual regression&lt;/strong&gt; — capture a page (or a specific element via &lt;code&gt;selector&lt;/code&gt;) before and after a deploy and diff them, without keeping a headless browser alive in CI.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Archiving&lt;/strong&gt; — a PDF snapshot of a contract, terms page or listing at a point in time.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Competitive/vendor tracking&lt;/strong&gt; — get a webhook when a competitor's pricing page or a vendor's ToS actually changes, instead of checking manually.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Limits, honestly
&lt;/h2&gt;

&lt;p&gt;Free tier is 200 screenshots/month and 3 monitored pages checked every 6h — enough to try it, not enough to run serious production monitoring on. Paid plans (from €9/month) raise both the screenshot quota and the check frequency, and add webhook alerts. Full parameters and error codes are in the &lt;a href="https://screenshot-api-production-ffd7.up.railway.app/docs?utm_source=devto&amp;amp;utm_campaign=pdf_monitoring" rel="noopener noreferrer"&gt;docs&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;If you're already generating PDFs or diffing screenshots with your own Puppeteer/Playwright setup and it's working fine, this isn't trying to talk you out of that. If you're the one who gets paged when that setup breaks, this is meant to remove that job, not replace a tool you like.&lt;/p&gt;

&lt;p&gt;Curious whether people doing visual regression testing today are rolling their own diffing, or using a dedicated tool for it — what does that stack actually look like for you?&lt;/p&gt;

</description>
      <category>pdf</category>
      <category>api</category>
      <category>webdev</category>
      <category>testing</category>
    </item>
    <item>
      <title>If you're still maintaining your own Playwright/Puppeteer screenshot service, here's what it usually costs</title>
      <dc:creator>Ghezam Capital</dc:creator>
      <pubDate>Tue, 22 Sep 2026 19:55:43 +0000</pubDate>
      <link>https://dev.to/ghezam_capital_0898/if-youre-still-maintaining-your-own-playwrightpuppeteer-screenshot-service-heres-what-it-1c27</link>
      <guid>https://dev.to/ghezam_capital_0898/if-youre-still-maintaining-your-own-playwrightpuppeteer-screenshot-service-heres-what-it-1c27</guid>
      <description>&lt;h2&gt;
  
  
  The pattern
&lt;/h2&gt;

&lt;p&gt;If you've built your own screenshot service on Playwright or&lt;br&gt;
Puppeteer, this list probably looks familiar:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Zombie Chromium processes eating RAM after a crash (a cron job
that runs &lt;code&gt;kill -9&lt;/code&gt; on stray browser processes is a common fix —
see &lt;a href="https://medium.com/@TheTechDude/puppeteer-memory-leaks-crashes-and-zombie-processes-6-months-of-screenshots-in-production-b2ae7e65df3f" rel="noopener noreferrer"&gt;this writeup&lt;/a&gt;)- Memory creeping up until the box gets OOM-killed&lt;/li&gt;
&lt;li&gt;A hard ceiling on concurrent pages before things degrade&lt;/li&gt;
&lt;li&gt;Someone has to own the 3am page when it falls over&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;None of this means Playwright/Puppeteer are bad tools — they're not.&lt;br&gt;
It means running them reliably in production is its own job, on top&lt;br&gt;
of whatever you're actually building.&lt;/p&gt;

&lt;h2&gt;
  
  
  What I built instead
&lt;/h2&gt;

&lt;p&gt;Screenshot Happy is a hosted screenshot API. It still runs Playwright&lt;br&gt;
under the hood — we haven't reinvented that part. What changes is who&lt;br&gt;
owns keeping it alive: &lt;code&gt;GET /screenshot?url=...&lt;/code&gt; → PNG/JPEG/PDF, full&lt;br&gt;
page or a CSS selector, custom viewport. Free tier: 200 screenshots/&lt;br&gt;
month, no card.&lt;/p&gt;

&lt;p&gt;The other thing it does, if you need it: &lt;code&gt;POST /monitors&lt;/code&gt; — point it&lt;br&gt;
at a URL with an interval and a webhook, it screenshots on schedule,&lt;br&gt;
diffs against the last capture, and calls your webhook when something&lt;br&gt;
changes.&lt;/p&gt;

&lt;h2&gt;
  
  
  Honest caveat
&lt;/h2&gt;

&lt;p&gt;This is a small, new project — a handful of competitors have been at&lt;br&gt;
this longer (ScreenshotOne, Urlbox, ApiFlash among others). If you're&lt;br&gt;
already happy maintaining your own setup, this isn't trying to talk&lt;br&gt;
you out of it. If you're tired of owning the infra side of it, this&lt;br&gt;
is for that.&lt;/p&gt;

&lt;p&gt;Docs: &lt;a href="https://screenshot-api-production-ffd7.up.railway.app/docs?utm_source=devto&amp;amp;utm_campaign=infra-fatiga" rel="noopener noreferrer"&gt;https://screenshot-api-production-ffd7.up.railway.app/docs?utm_source=devto&amp;amp;utm_campaign=infra-fatiga&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Curious if this pattern (self-hosted Playwright → managed API) matches&lt;br&gt;
what others have run into, or if I'm overestimating how common it is.&lt;/p&gt;

</description>
      <category>playwright</category>
      <category>puppeteer</category>
      <category>showdev</category>
      <category>node</category>
    </item>
    <item>
      <title>You don't need to run your own Playwright/Puppeteer setup just for screenshots</title>
      <dc:creator>Ghezam Capital</dc:creator>
      <pubDate>Tue, 22 Sep 2026 13:45:34 +0000</pubDate>
      <link>https://dev.to/ghezam_capital_0898/you-dont-need-to-run-your-own-playwrightpuppeteer-setup-just-for-screenshots-1d78</link>
      <guid>https://dev.to/ghezam_capital_0898/you-dont-need-to-run-your-own-playwrightpuppeteer-setup-just-for-screenshots-1d78</guid>
      <description>&lt;p&gt;A lot of teams end up running their own headless browser just to generate&lt;br&gt;
a PNG or a PDF of a page. It starts as a few lines of Puppeteer or&lt;br&gt;
Playwright code. It doesn't always stay that simple.&lt;/p&gt;

&lt;p&gt;Where it usually goes&lt;/p&gt;

&lt;p&gt;Once a screenshot script moves from your laptop into production, it&lt;br&gt;
tends to pick up a few jobs it didn't have before:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;- - Keeping Chromium processes from piling up after a crash or a timeout&lt;/li&gt;
&lt;li&gt;- - Watching memory, because a long-running headless browser process can&lt;/li&gt;
&lt;li&gt;-   grow over time&lt;/li&gt;
&lt;li&gt;- - Capping how many pages run at once, since concurrency has a ceiling&lt;/li&gt;
&lt;li&gt;-   before things degrade&lt;/li&gt;
&lt;li&gt;- - Owning the alert when a job queue backs up or a page never returns&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;None of this means Playwright or Puppeteer are broken tools — they're&lt;br&gt;
not. Most hosted screenshot services, this one included, are built on&lt;br&gt;
top of them. It just means that once it's running unattended, "take a&lt;br&gt;
screenshot" quietly turns into "run and babysit a browser," which is a&lt;br&gt;
different job than the one most people signed up for. &lt;a href="https://medium.com/@TheTechDude/puppeteer-memory-leaks-crashes-and-zombie-processes-6-months-of-screenshots-in-production-b2ae7e65df3f" rel="noopener noreferrer"&gt;This writeup&lt;/a&gt;&lt;br&gt;
from someone who ran Puppeteer screenshots in production for six months&lt;br&gt;
is a good look at what that job actually involves day to day.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;What Screenshot Happy does differently&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Screenshot Happy is a hosted API. It still runs Playwright under the&lt;br&gt;
hood — that part isn't magic, it's the same tool everyone else uses.&lt;br&gt;
What changes is who's responsible for keeping it alive:&lt;br&gt;
&lt;code&gt;GET /screenshot?url=...&lt;/code&gt; returns a PNG, JPEG or PDF. You don't&lt;br&gt;
provision, patch, restart, or clean up after it.&lt;/p&gt;

&lt;p&gt;If you also need to catch when a page changes — a competitor's&lt;br&gt;
pricing, a vendor's terms — there's a scheduling mode too, but that's&lt;br&gt;
a separate feature, not the point of this post.&lt;/p&gt;

&lt;p&gt;Free tier: 200 screenshots/month, no card required, if you want to see&lt;br&gt;
what the output actually looks like before deciding anything:&lt;br&gt;
&lt;a href="https://screenshot-api-production-ffd7.up.railway.app/docs?utm_source=devto&amp;amp;utm_medium=article&amp;amp;utm_campaign=playwright_infrastructure" rel="noopener noreferrer"&gt;https://screenshot-api-production-ffd7.up.railway.app/docs?utm_source=devto&amp;amp;utm_medium=article&amp;amp;utm_campaign=playwright_infrastructure&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Honest caveat&lt;br&gt;
This is a small, recently-launched project. There are more established&lt;br&gt;
screenshot APIs out there (ScreenshotOne, Urlbox, ApiFlash among&lt;br&gt;
others) that have been doing this longer, and I'm not going to pretend&lt;br&gt;
otherwise. If your current setup works and nobody's getting paged for&lt;br&gt;
it, there's no real reason to switch. This is aimed at the setups&lt;br&gt;
where that's not quite true anymore.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Question&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If you're running your own Playwright/Puppeteer screenshot service&lt;br&gt;
today — is infrastructure actually the annoying part, or is it&lt;br&gt;
something else (accuracy, speed, cost)? Genuinely curious where this&lt;br&gt;
breaks down for people who've actually dealt with it.&lt;/p&gt;

</description>
      <category>playwright</category>
      <category>puppeteer</category>
      <category>opensource</category>
      <category>node</category>
    </item>
    <item>
      <title>[Boost]</title>
      <dc:creator>Ghezam Capital</dc:creator>
      <pubDate>Mon, 21 Sep 2026 19:16:39 +0000</pubDate>
      <link>https://dev.to/ghezam_capital_0898/-3o4l</link>
      <guid>https://dev.to/ghezam_capital_0898/-3o4l</guid>
      <description>&lt;div class="ltag__link--embedded"&gt;
  &lt;div class="crayons-story "&gt;
  &lt;a href="https://dev.to/ghezam_capital_0898/i-built-a-screenshot-api-that-can-also-tell-you-when-a-website-changes-4p4e" class="crayons-story__hidden-navigation-link"&gt;I built a screenshot API that can also tell you when a website changes&lt;/a&gt;


  &lt;div class="crayons-story__body crayons-story__body-full_post"&gt;
    &lt;div class="crayons-story__top"&gt;
      &lt;div class="crayons-story__meta"&gt;
        &lt;div class="crayons-story__author-pic"&gt;

          &lt;a href="/ghezam_capital_0898" class="crayons-avatar  crayons-avatar--l  "&gt;
            &lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F4136072%2F96b80bf5-d8e1-4bba-8780-1a3c0bc32bbc.png" alt="ghezam_capital_0898 profile" class="crayons-avatar__image"&gt;
          &lt;/a&gt;
        &lt;/div&gt;
        &lt;div&gt;
          &lt;div&gt;
            &lt;a href="/ghezam_capital_0898" class="crayons-story__secondary fw-medium m:hidden"&gt;
              Ghezam Capital
            &lt;/a&gt;
            &lt;div class="profile-preview-card relative mb-4 s:mb-0 fw-medium hidden m:inline-block"&gt;
              
                Ghezam Capital
                
                
              
              &lt;div id="story-author-preview-content-4709283" class="profile-preview-card__content crayons-dropdown branded-7 p-4 pt-0"&gt;
                &lt;div class="gap-4 grid"&gt;
                  &lt;div class="-mt-4"&gt;
                    &lt;a href="/ghezam_capital_0898" class="flex"&gt;
                      &lt;span class="crayons-avatar crayons-avatar--xl mr-2 shrink-0"&gt;
                        &lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F4136072%2F96b80bf5-d8e1-4bba-8780-1a3c0bc32bbc.png" class="crayons-avatar__image" alt=""&gt;
                      &lt;/span&gt;
                      &lt;span class="crayons-link crayons-subtitle-2 mt-5"&gt;Ghezam Capital&lt;/span&gt;
                    &lt;/a&gt;
                  &lt;/div&gt;
                  &lt;div class="print-hidden"&gt;
                    
                      Follow
                    
                  &lt;/div&gt;
                  &lt;div class="author-preview-metadata-container"&gt;&lt;/div&gt;
                &lt;/div&gt;
              &lt;/div&gt;
            &lt;/div&gt;

          &lt;/div&gt;
          &lt;a href="https://dev.to/ghezam_capital_0898/i-built-a-screenshot-api-that-can-also-tell-you-when-a-website-changes-4p4e" class="crayons-story__tertiary fs-xs"&gt;&lt;time&gt;Sep 21&lt;/time&gt;&lt;span class="time-ago-indicator-initial-placeholder"&gt;&lt;/span&gt;&lt;/a&gt;
        &lt;/div&gt;
      &lt;/div&gt;

    &lt;/div&gt;

    &lt;div class="crayons-story__indention"&gt;
      &lt;h2 class="crayons-story__title crayons-story__title-full_post"&gt;
        &lt;a href="https://dev.to/ghezam_capital_0898/i-built-a-screenshot-api-that-can-also-tell-you-when-a-website-changes-4p4e" id="article-link-4709283"&gt;
          I built a screenshot API that can also tell you when a website changes
        &lt;/a&gt;
      &lt;/h2&gt;
        &lt;div class="crayons-story__tags"&gt;
            &lt;a class="crayons-tag crayons-tag--filled  " href="/t/showdev"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;showdev&lt;/a&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/productivity"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;productivity&lt;/a&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/javascript"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;javascript&lt;/a&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/api"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;api&lt;/a&gt;
        &lt;/div&gt;
      &lt;div class="crayons-story__bottom"&gt;
        &lt;div class="crayons-story__details"&gt;
            &lt;a href="https://dev.to/ghezam_capital_0898/i-built-a-screenshot-api-that-can-also-tell-you-when-a-website-changes-4p4e#comments" class="crayons-btn crayons-btn--s crayons-btn--ghost crayons-btn--icon-left flex items-center"&gt;
              

              1&lt;span class="hidden s:inline"&gt;&amp;nbsp;comment&lt;/span&gt;
            &lt;/a&gt;
        &lt;/div&gt;
        &lt;div class="crayons-story__save"&gt;
          &lt;small class="crayons-story__tertiary fs-xs mr-2"&gt;
            1 min read
          &lt;/small&gt;
        &lt;/div&gt;
      &lt;/div&gt;
    &lt;/div&gt;
  &lt;/div&gt;
&lt;/div&gt;

&lt;/div&gt;


</description>
    </item>
    <item>
      <title>I built a screenshot API that can also tell you when a website changes</title>
      <dc:creator>Ghezam Capital</dc:creator>
      <pubDate>Mon, 21 Sep 2026 16:11:15 +0000</pubDate>
      <link>https://dev.to/ghezam_capital_0898/i-built-a-screenshot-api-that-can-also-tell-you-when-a-website-changes-4p4e</link>
      <guid>https://dev.to/ghezam_capital_0898/i-built-a-screenshot-api-that-can-also-tell-you-when-a-website-changes-4p4e</guid>
      <description>&lt;p&gt;I kept finding myself writing small Playwright/Puppeteer scripts whenever I needed screenshots of websites.&lt;/p&gt;

&lt;p&gt;So I decided to turn that into an API.&lt;/p&gt;

&lt;p&gt;Screenshot Happy can generate:&lt;/p&gt;

&lt;p&gt;PNG, JPEG and PDF screenshots&lt;br&gt;
Full-page screenshots&lt;br&gt;
Screenshots of specific elements using CSS selectors&lt;br&gt;
Custom viewport sizes&lt;br&gt;
Automated website monitoring&lt;br&gt;
Webhooks when a monitored page changes&lt;br&gt;
The monitoring part is what made the project more interesting to me.&lt;/p&gt;

&lt;p&gt;For example, you could monitor:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A competitor’s pricing page&lt;/li&gt;
&lt;li&gt;Documentation&lt;/li&gt;
&lt;li&gt;Terms and conditions&lt;/li&gt;
&lt;li&gt;Product pages&lt;/li&gt;
&lt;li&gt;Any webpage where you need to know when something changes&lt;/li&gt;
&lt;li&gt;The API can detect a visual change and send a webhook instead of requiring you to constantly check the page yourself.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;There’s a free plan with 200 screenshots/month and 3 monitored pages, so you can try it without paying.&lt;/p&gt;

&lt;p&gt;I’m currently trying to figure out whether the monitoring side is actually useful enough for developers to use regularly.&lt;/p&gt;

&lt;p&gt;If you work with Playwright, Puppeteer, testing, monitoring or web automation:&lt;/p&gt;

&lt;p&gt;What would you want an API like this to do that it doesn’t do yet?&lt;/p&gt;

&lt;p&gt;I’d genuinely appreciate feedback, especially if you think the idea is useless. Those comments are usually more valuable than “looks cool.” 😅&lt;/p&gt;

&lt;p&gt;Docs: &lt;a href="https://screenshot-api-production-ffd7.up.railway.app/docs" rel="noopener noreferrer"&gt;https://screenshot-api-production-ffd7.up.railway.app/docs&lt;/a&gt;&lt;br&gt;
_&lt;/p&gt;

</description>
      <category>showdev</category>
      <category>productivity</category>
      <category>javascript</category>
      <category>api</category>
    </item>
  </channel>
</rss>
