<?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: Nawal Shrestha</title>
    <description>The latest articles on DEV Community by Nawal Shrestha (@nawalshrestha).</description>
    <link>https://dev.to/nawalshrestha</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%2F4160809%2Fef25d13b-f6fd-408d-a12a-eb7a5b3ba956.png</url>
      <title>DEV Community: Nawal Shrestha</title>
      <link>https://dev.to/nawalshrestha</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/nawalshrestha"/>
    <language>en</language>
    <item>
      <title>Image Optimization for Core Web Vitals: Fix Your LCP</title>
      <dc:creator>Nawal Shrestha</dc:creator>
      <pubDate>Sat, 24 Oct 2026 04:26:08 +0000</pubDate>
      <link>https://dev.to/nawalshrestha/image-optimization-for-core-web-vitals-fix-your-lcp-4mlp</link>
      <guid>https://dev.to/nawalshrestha/image-optimization-for-core-web-vitals-fix-your-lcp-4mlp</guid>
      <description>&lt;h1&gt;
  
  
  Image Optimization for Core Web Vitals: Fix Your LCP
&lt;/h1&gt;

&lt;p&gt;You run Lighthouse on the homepage. The score lands at 47, painted in angry red. Largest Contentful Paint sits at 5.8 seconds, and when you dig into the trace, the culprit is embarrassing: a 2.1MB hero JPEG, served at full desktop resolution to a phone.&lt;/p&gt;

&lt;p&gt;Welcome to image optimization core web vitals work: the unglamorous, high-leverage job of making your pictures weigh less. LCP is the most image-driven of the three Core Web Vitals, and images are almost always the heaviest thing on the page.&lt;/p&gt;

&lt;p&gt;Unlike most Core Web Vitals guides, this one gives you concrete KB budgets per image type and a worked audit you can repeat in DevTools. I build SnapShrink, a 100%-in-browser image compressor, so shrinking pictures is quite literally my day job.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why LCP is usually an image problem
&lt;/h2&gt;

&lt;p&gt;LCP measures when the largest visible element on screen finishes rendering, and on most pages that element is an image: a hero banner, a product photo, a featured post image. Text and CSS arrive in milliseconds, while a 2MB picture takes seconds on a mobile connection. Since Google wants LCP &lt;a href="https://developers.google.com/search/docs/appearance/core-web-vitals" rel="noopener noreferrer"&gt;under 2.5 seconds&lt;/a&gt;, image weight is usually the whole battle.&lt;/p&gt;

&lt;p&gt;Here is the math that makes it obvious. The HTML, CSS, and fonts on a typical marketing page weigh 100 to 300KB combined. One unoptimized hero image can weigh ten times that. The LCP element has to download, decode, and paint before the metric stops, so every extra megabyte stretches the timeline on a real mobile connection. Shrink the image and the metric usually follows.&lt;/p&gt;

&lt;h2&gt;
  
  
  Find your LCP image in under two minutes
&lt;/h2&gt;

&lt;p&gt;Open Chrome DevTools, run Lighthouse from the Performance panel, and open the generated report. Scroll to the LCP element in the diagnostics section and click it; DevTools highlights the exact image on your page and shows its size and format. Note the file weight and the rendered dimensions, because the gap between the two is where your savings live.&lt;/p&gt;

&lt;p&gt;The routine, step by step:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Run Lighthouse on the page with mobile emulation on. The default settings are fine; you want the same conditions Google scores.&lt;/li&gt;
&lt;li&gt;In the report, find "Largest Contentful Paint element" under Diagnostics and click it. DevTools jumps straight to the image in the Elements panel.&lt;/li&gt;
&lt;li&gt;Compare natural and rendered dimensions. If the file is 2400 pixels wide but renders at 390, you are shipping six times the pixels anyone sees.&lt;/li&gt;
&lt;li&gt;Cross-check in the Network tab: filter by Img, sort by Size, reload with the cache disabled. The heaviest files float to the top, and the LCP image is usually one of the first three rows.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Set a KB budget before you touch a codec
&lt;/h2&gt;

&lt;p&gt;Every image optimization core web vitals project I have run started with a budget, not a compressor. Decide the file size each image type is allowed before you touch anything: hero images get 150KB on desktop, 80KB on mobile; thumbnails get 30KB; avatars and icons get 15KB or ship as SVG. A budget turns optimization into a number you can verify.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Image type&lt;/th&gt;
&lt;th&gt;Desktop budget&lt;/th&gt;
&lt;th&gt;Mobile budget&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Hero / banner&lt;/td&gt;
&lt;td&gt;150KB&lt;/td&gt;
&lt;td&gt;80KB&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Product / feature shots&lt;/td&gt;
&lt;td&gt;100KB&lt;/td&gt;
&lt;td&gt;60KB&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Card thumbnails&lt;/td&gt;
&lt;td&gt;30KB&lt;/td&gt;
&lt;td&gt;30KB&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Avatars / icons&lt;/td&gt;
&lt;td&gt;15KB (or SVG)&lt;/td&gt;
&lt;td&gt;15KB (or SVG)&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;These are the ceilings I start from. They assume photographic content saved as WebP at quality 75 to 85. Illustrations and screenshots with flat colors compress far better, so treat the numbers as ceilings to stay under. If you like working backwards from the number, you can &lt;a href="https://getsnapshrink.com/compress-image-to-100kb/" rel="noopener noreferrer"&gt;compress an image to an exact KB target&lt;/a&gt; in the browser instead of guessing at quality sliders.&lt;/p&gt;

&lt;h2&gt;
  
  
  The re-encode walkthrough: 2.1MB to about 110KB
&lt;/h2&gt;

&lt;p&gt;Take the 2.1MB hero from our Lighthouse trace: a 2400x1600 JPEG served to every device. Resize it to the largest width the layout actually renders, 1600 pixels here, re-encode it to WebP at quality 80, and the file drops to roughly 100 to 140KB with no visible difference on screen. That single change typically cuts LCP by two to four seconds on a mobile connection.&lt;/p&gt;

&lt;p&gt;The loop, in order:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Resize to the rendered width first. If the layout never shows the hero wider than 1600 pixels, a 2400-pixel source is pure wasted bytes. Resizing is the cheapest win in the whole process.&lt;/li&gt;
&lt;li&gt;Pick WebP as your default. For photographic content it typically cuts 25 to 35 percent off an equivalent-quality JPEG. Keep the JPEG only if you still support truly ancient browsers; everything modern renders WebP.&lt;/li&gt;
&lt;li&gt;Set quality between 75 and 85. Below 75, banding creeps into skies and gradients. Above 85, the file size climbs fast for differences nobody can see. I default to 80 and adjust by eye.&lt;/li&gt;
&lt;li&gt;Compare the result against the original at 100 percent zoom. If you cannot spot the difference on a careful look, your users will not spot it at all. Ship it.&lt;/li&gt;
&lt;li&gt;Re-run Lighthouse. The LCP number should move a lot. If it barely budges, the LCP element was not the file you optimized, and the audit in the second section sent you to the wrong image.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;I built &lt;a href="https://getsnapshrink.com/compress-image/" rel="noopener noreferrer"&gt;SnapShrink's free browser-based image compressor&lt;/a&gt; for exactly this loop: drop in the hero, resize, pick WebP, and everything re-encodes on your machine with nothing uploaded.&lt;/p&gt;

&lt;h2&gt;
  
  
  Your image optimization core web vitals questions, answered
&lt;/h2&gt;

&lt;p&gt;Three questions come up every time image optimization core web vitals work lands on a developer's desk: whether lazy loading fixes LCP, whether AVIF is worth the hassle, and whether compression or responsive images matter more. Here are the short answers, with the tradeoffs that change the decision in practice.&lt;/p&gt;

&lt;h3&gt;
  
  
  Will lazy-loading the hero fix my LCP?
&lt;/h3&gt;

&lt;p&gt;No. It usually makes LCP worse. &lt;a href="https://web.dev/articles/browser-level-image-lazy-loading" rel="noopener noreferrer"&gt;Lazy loading&lt;/a&gt; defers offscreen images, but the LCP image is on screen by definition, so you would be adding delay to the exact thing you are trying to speed up. Mark the LCP image with fetchpriority="high", consider a preload link for it, and lazy-load everything below the fold. Google's guide to &lt;a href="https://web.dev/articles/optimize-lcp" rel="noopener noreferrer"&gt;optimizing LCP&lt;/a&gt; walks through prioritizing the LCP element in detail.&lt;/p&gt;

&lt;h3&gt;
  
  
  Is AVIF worth switching to?
&lt;/h3&gt;

&lt;p&gt;Not as your first move. AVIF typically shaves another 15 to 25 percent off WebP at matched visual quality, but encoding is slower and the tooling is thinner. Nail WebP first; add AVIF later.&lt;/p&gt;

&lt;h3&gt;
  
  
  Compression or responsive images: which first?
&lt;/h3&gt;

&lt;p&gt;Compression first, responsive images second. Re-encoding one hero from JPEG to WebP can remove 70 to 90 percent of its weight in ten minutes. Responsive images with srcset and sizes stop you shipping desktop pixels to phones, which matters, but it is a code change across templates. Do the quick win this afternoon; schedule the srcset work for the sprint.&lt;/p&gt;

&lt;p&gt;Back to that homepage scoring 47. Find the LCP image, give it a KB budget, re-encode it, and run Lighthouse again. LCP should drop hard, and the score usually follows it into the green. One page, one image, one afternoon.&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>performance</category>
      <category>webperf</category>
      <category>seo</category>
    </item>
    <item>
      <title>WebP vs PNG vs JPEG: Which Format Should You Serve in 2026?</title>
      <dc:creator>Nawal Shrestha</dc:creator>
      <pubDate>Wed, 21 Oct 2026 04:38:16 +0000</pubDate>
      <link>https://dev.to/nawalshrestha/webp-vs-png-vs-jpeg-which-format-should-you-serve-in-2026-207c</link>
      <guid>https://dev.to/nawalshrestha/webp-vs-png-vs-jpeg-which-format-should-you-serve-in-2026-207c</guid>
      <description>&lt;h1&gt;
  
  
  WebP vs PNG vs JPEG: Which Format Should You Serve in 2026?
&lt;/h1&gt;

&lt;p&gt;Last week I ran SnapShrink's batch converter over a folder of 200 demo images for the tool's gallery. One PNG screenshot went in at 412 KB and came out at 96 KB as WebP. Same pixels, no visible difference. That folder is why I stopped treating webp vs png as a taste question. It's arithmetic now. Here's how I decide what to serve.&lt;/p&gt;

&lt;h2&gt;
  
  
  WebP vs PNG: how much smaller is WebP, really?
&lt;/h2&gt;

&lt;p&gt;WebP is consistently smaller than PNG. Google's published WebP study measured lossless WebP at roughly 26% smaller than equivalent PNG files, and lossy WebP at 25 to 34% smaller than JPEG at comparable visual quality. Savings vary by image, but for anything served on a website, WebP almost always wins on size.&lt;/p&gt;

&lt;p&gt;The catch is that WebP has two modes and they behave very differently. Lossy WebP is what you want for photos. Lossless WebP is what you want for screenshots, logos, and anything with text or hard edges. Mixing them up is the most common mistake I see. Lossy on a screenshot smears the text; lossless on a photo wastes bytes for detail your eyes can't see.&lt;/p&gt;

&lt;p&gt;One honest caveat from building a converter: for very tiny or simple images, WebP's container overhead can wipe out the compression gain, and I've seen small icons where PNG came out ahead. Spot-check your own assets instead of trusting a rule.&lt;/p&gt;

&lt;h2&gt;
  
  
  WebP vs PNG for transparency and animation
&lt;/h2&gt;

&lt;p&gt;WebP supports 8-bit alpha transparency and animation, so it covers every job PNG does except one: legacy compatibility. PNG still wins when the destination app only reads PNG, like some email clients, design tools, and old CMS pipelines. For animation, WebP beats GIF on file size, but actual video formats beat both WebP and GIF by a wide margin.&lt;/p&gt;

&lt;p&gt;Transparency is the feature that made me stop defaulting to PNG. Early WebP had a reputation for rough alpha edges, but modern encoders handle it fine, and the files are much smaller. The one failure mode I watch for: converting a PNG with semi-transparent pixels and not checking the result. Alpha is the one thing that can break silently, so I always eyeball the converted file against a dark background.&lt;/p&gt;

&lt;p&gt;For animation, WebP is technically fine and far smaller than GIF, but the authoring and tooling ecosystem never caught up. Short looping clips belong in muted MP4 or WebM. They compress better than any image format and browsers play them natively.&lt;/p&gt;

&lt;h2&gt;
  
  
  Where JPEG still beats both
&lt;/h2&gt;

&lt;p&gt;JPEG wins on universal compatibility and encoding speed, not quality per byte. Every device built in the last twenty years reads JPEG, and encoding is instant. For photos served to old email clients, RSS readers, or user-uploaded avatars you don't control, JPEG at 80 to 85 quality remains the safe pick.&lt;/p&gt;

&lt;p&gt;JPEG also has no alpha channel and no lossless mode, so don't force it into jobs it can't do. Text screenshots saved as JPEG get that familiar smudged look around every letter, which is why it's the wrong tool for UI images. Use it for photos aimed at destinations you can't control, and use WebP or PNG for everything else.&lt;/p&gt;

&lt;h2&gt;
  
  
  The 2026 decision framework I actually use
&lt;/h2&gt;

&lt;p&gt;My rule is deliberately boring: photos and screenshots go to WebP, lossy for photos and lossless for anything with text or hard edges, with PNG reserved for tools that force it and JPEG for photos aimed at destinations I can't control. Everything gets wrapped in a picture element so the browser picks the best format it understands.&lt;/p&gt;

&lt;p&gt;The picture element does the heavy lifting, so your markup doesn't have to guess:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;picture&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;source&lt;/span&gt; &lt;span class="na"&gt;srcset=&lt;/span&gt;&lt;span class="s"&gt;"hero.avif"&lt;/span&gt; &lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;"image/avif"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;source&lt;/span&gt; &lt;span class="na"&gt;srcset=&lt;/span&gt;&lt;span class="s"&gt;"hero.webp"&lt;/span&gt; &lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;"image/webp"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;img&lt;/span&gt; &lt;span class="na"&gt;src=&lt;/span&gt;&lt;span class="s"&gt;"hero.jpg"&lt;/span&gt; &lt;span class="na"&gt;alt=&lt;/span&gt;&lt;span class="s"&gt;"Product dashboard screenshot"&lt;/span&gt; &lt;span class="na"&gt;width=&lt;/span&gt;&lt;span class="s"&gt;"1200"&lt;/span&gt; &lt;span class="na"&gt;height=&lt;/span&gt;&lt;span class="s"&gt;"630"&lt;/span&gt; &lt;span class="na"&gt;loading=&lt;/span&gt;&lt;span class="s"&gt;"lazy"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/picture&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Browsers read the sources top to bottom and take the first format they support. Old browsers fall through to the JPEG. You can add AVIF at the top of the stack later without touching anything else, which is exactly how I future-proofed the SnapShrink gallery.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Situation&lt;/th&gt;
&lt;th&gt;Serve this&lt;/th&gt;
&lt;th&gt;Why&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Photo on a modern site&lt;/td&gt;
&lt;td&gt;WebP lossy, ~75-82 quality&lt;/td&gt;
&lt;td&gt;Smallest file at good quality&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Screenshot, logo, UI with text&lt;/td&gt;
&lt;td&gt;WebP lossless&lt;/td&gt;
&lt;td&gt;Sharp edges, alpha support, far smaller than PNG&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Destination only accepts PNG&lt;/td&gt;
&lt;td&gt;PNG&lt;/td&gt;
&lt;td&gt;Compatibility beats bytes&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Photo for email, RSS, unknown clients&lt;/td&gt;
&lt;td&gt;JPEG, 80-85 quality&lt;/td&gt;
&lt;td&gt;Universal support, instant encode&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Short looping animation&lt;/td&gt;
&lt;td&gt;Muted MP4/WebM&lt;/td&gt;
&lt;td&gt;Beats every image format on size&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Simple icon&lt;/td&gt;
&lt;td&gt;SVG, or PNG if raster&lt;/td&gt;
&lt;td&gt;Vector scales; PNG is the safe raster&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h2&gt;
  
  
  How to convert without breaking things
&lt;/h2&gt;

&lt;p&gt;Convert originals to WebP at build or upload time, never by hand-editing files on a live server. Keep your PNG masters archived for anything an external tool might need later, and always check alpha channels after conversion, since a broken alpha channel fails silently and looks terrible on dark backgrounds.&lt;/p&gt;

&lt;p&gt;If you want the full file-size numbers and the technical background in one place, I've written a deeper &lt;a href="https://getsnapshrink.com/blog/webp-vs-png/" rel="noopener noreferrer"&gt;WebP vs PNG comparison on the SnapShrink blog&lt;/a&gt;. And for the reverse trip, when some tool insists on a PNG, SnapShrink's &lt;a href="https://getsnapshrink.com/webp-to-png/" rel="noopener noreferrer"&gt;free WebP to PNG converter&lt;/a&gt; handles the conversion in your browser with no upload.&lt;/p&gt;

&lt;p&gt;Two practical gotchas before you convert a whole library. First, social and chat link previews still prefer JPEG or PNG for og:image, so don't WebP your share images. Second, WebP doesn't magically fix a bad source: a blurry JPEG converted to WebP is a small blurry image. Start from the highest-quality original you have.&lt;/p&gt;

&lt;h2&gt;
  
  
  FAQ
&lt;/h2&gt;

&lt;p&gt;The short version of everything above: serve WebP by default, keep PNG for compatibility, use JPEG for photos aimed at old clients, and try AVIF behind WebP in your picture element if you feel like experimenting. The questions below cover the edge cases I get asked most.&lt;/p&gt;

&lt;h3&gt;
  
  
  Is WebP always smaller than PNG?
&lt;/h3&gt;

&lt;p&gt;No. For most web images, yes, and usually by a lot. But for very small or very simple images, WebP's container overhead can eat the gain, and PNG sometimes comes out ahead. Test your own assets instead of trusting a blanket rule.&lt;/p&gt;

&lt;h3&gt;
  
  
  Should I convert my entire PNG library to WebP?
&lt;/h3&gt;

&lt;p&gt;Only the files you actually serve on the web. Keep PNG masters archived. Re-converting from a lossy WebP back to PNG later is a one-way trip you don't want to take.&lt;/p&gt;

&lt;h3&gt;
  
  
  What about AVIF?
&lt;/h3&gt;

&lt;p&gt;AVIF typically compresses 20 to 30% smaller than WebP's lossy mode, but encoding is noticeably slower and tooling support is still catching up. It's worth trying behind a picture element where WebP is the fallback. Don't rebuild your whole pipeline around it yet.&lt;/p&gt;

&lt;h3&gt;
  
  
  Does WebP work in every browser?
&lt;/h3&gt;

&lt;p&gt;All modern browsers have supported WebP since around 2020, including Safari from version 14. The picture element pattern above covers the stragglers with a JPEG fallback, so browser support shouldn't stop you.&lt;/p&gt;

&lt;p&gt;Remember that 412 KB screenshot from the demo folder? It shipped as a 96 KB WebP and nobody noticed except me, checking the network tab. That's the whole pitch. Pick WebP as your default, keep PNG and JPEG for the jobs they still own, and let the picture element sort out the rest. Your users' bandwidth will thank you.&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>webperf</category>
      <category>images</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>JFIF to JPG, WebP to GIF, HEIC to PNG Explained</title>
      <dc:creator>Nawal Shrestha</dc:creator>
      <pubDate>Sat, 17 Oct 2026 04:26:34 +0000</pubDate>
      <link>https://dev.to/nawalshrestha/jfif-to-jpg-webp-to-gif-heic-to-png-explained-4if8</link>
      <guid>https://dev.to/nawalshrestha/jfif-to-jpg-webp-to-gif-heic-to-png-explained-4if8</guid>
      <description>&lt;h1&gt;
  
  
  JFIF to JPG, WebP to GIF, HEIC to PNG: Three Conversions That Confuse Everyone
&lt;/h1&gt;

&lt;p&gt;You hit Save, and instead of photo.jpg you get photo.jfif. The upload form rejects it. You stare at the extension like it personally wronged you.&lt;/p&gt;

&lt;p&gt;I build SnapShrink, a browser-based image tool, so I collect these moments. That .jfif confusion is one of three format conversions that trip up basically everyone. The other two: a WebP animation the platform won't accept, and iPhone photos that won't open on Windows. Here's what each one actually is, and the fastest way through it.&lt;/p&gt;

&lt;h2&gt;
  
  
  1. JFIF to JPG: the format you've used without knowing
&lt;/h2&gt;

&lt;p&gt;If you've ever saved an image and gotten a &lt;code&gt;.jfif&lt;/code&gt; file instead of &lt;code&gt;.jpg&lt;/code&gt;, you've met JFIF. Despite the unfamiliar extension, it's a JPEG under the hood — JFIF (JPEG File Interchange Format) is just a slightly different container for the same data. Your camera, your phone, and half the software on your computer treat them as the same thing.&lt;/p&gt;

&lt;p&gt;The problem is the other half. Some upload forms, older editors, and picky CMS platforms reject &lt;code&gt;.jfif&lt;/code&gt; outright because the extension isn't on their allowlist. The file is fine; the extension is the problem.&lt;/p&gt;

&lt;p&gt;The fix takes seconds: converting JFIF to JPG just rewrites the container, no recompression, no quality loss. I run a &lt;a href="https://getsnapshrink.com/jfif-to-jpg/" rel="noopener noreferrer"&gt;free JFIF to JPG converter&lt;/a&gt; for exactly this — drop the file in, get a &lt;code&gt;.jpg&lt;/code&gt; back, upload wherever you were blocked.&lt;/p&gt;

&lt;h2&gt;
  
  
  2. WebP to GIF: when you need the animation, not the efficiency
&lt;/h2&gt;

&lt;p&gt;WebP is the better format on paper. Smaller files than JPEG, supports transparency like PNG, and handles animation too. Google's been pushing it for a decade and browsers finally all support it.&lt;/p&gt;

&lt;p&gt;But "better on paper" doesn't matter when the tool on the other end doesn't accept it. Email clients, some chat apps, forum software from 2015, design tools with frozen feature sets — plenty of places still only speak GIF for animations. I hit this making demo clips: record as WebP, then discover the platform I'm posting to wants GIF.&lt;/p&gt;

&lt;p&gt;Converting WebP to GIF re-encodes the animation frames. Quality takes a small hit (GIF is limited to 256 colors per frame), so keep the source WebP archived. For the actual conversion I use an &lt;a href="https://getsnapshrink.com/webp-to-gif/" rel="noopener noreferrer"&gt;in-browser WebP to GIF tool&lt;/a&gt; — nothing uploads anywhere, which matters when the clip is client work.&lt;/p&gt;

&lt;h2&gt;
  
  
  3. HEIC to PNG: iPhone photos on a Windows machine
&lt;/h2&gt;

&lt;p&gt;This is the one that generates the most confused messages. You AirDrop or transfer photos from an iPhone to a Windows PC, and half of them won't open. Those are HEIC files — Apple's default photo format since iOS 11. It's genuinely good tech (about half the file size of JPEG at the same quality), but Windows support is still patchy in 2026.&lt;/p&gt;

&lt;p&gt;PNG is the safe target here, not JPG. If you're pulling photos off a phone to edit or archive, PNG keeps every pixel — no generational loss on top of whatever the phone already did. JPG is fine for sharing; PNG is right for keeping.&lt;/p&gt;

&lt;p&gt;The conversion is straightforward with a &lt;a href="https://getsnapshrink.com/heic-to-png/" rel="noopener noreferrer"&gt;HEIC to PNG converter&lt;/a&gt;. One thing to watch: HEIC files sometimes contain multiple images (bursts, live photo frames). A decent converter handles the primary image; if you need every frame of a burst, that's a separate job.&lt;/p&gt;

&lt;h2&gt;
  
  
  A note on where the conversion happens
&lt;/h2&gt;

&lt;p&gt;All three tools I linked above run entirely in your browser. Most people never check this: the majority of "free online converters" upload your file to a server, convert it there, and hand it back. For a meme, who cares. For client photos, unreleased product shots, or anything with people in it, that upload is a privacy decision you're making without realizing it.&lt;/p&gt;

&lt;p&gt;You can verify the browser-only claim yourself in about ten seconds: open DevTools, go to the Network tab, run a conversion. If the network stays quiet, the file never left your machine. I built SnapShrink this way because I got tired of wondering where my files went.&lt;/p&gt;

&lt;h2&gt;
  
  
  The short version
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;JFIF → JPG&lt;/strong&gt;: same image, friendlier extension. Container swap, zero quality loss.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;WebP → GIF&lt;/strong&gt;: for the platforms stuck in 2015. Real re-encode, keep your source.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;HEIC → PNG&lt;/strong&gt;: iPhone photos on Windows. PNG for archiving, JPG for sharing.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Check where conversion happens&lt;/strong&gt; before uploading anything you wouldn't post publicly.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Three conversions, three tools, no accounts, no uploads. And next time a save dialog hands you a .jfif, you'll know exactly what it is — and exactly where to take it.&lt;/p&gt;

</description>
      <category>image</category>
      <category>webdev</category>
      <category>tutorial</category>
      <category>beginners</category>
    </item>
    <item>
      <title>I compared TinyPNG alternatives on privacy, not just file size</title>
      <dc:creator>Nawal Shrestha</dc:creator>
      <pubDate>Wed, 07 Oct 2026 16:15:41 +0000</pubDate>
      <link>https://dev.to/nawalshrestha/i-compared-tinypng-alternatives-on-privacy-not-just-file-size-1l6j</link>
      <guid>https://dev.to/nawalshrestha/i-compared-tinypng-alternatives-on-privacy-not-just-file-size-1l6j</guid>
      <description>&lt;p&gt;Everyone's used TinyPNG. It's the default "make this image smaller" tool, and its compression is genuinely good. But every roundup I read compares these tools on file size alone, and in 2026 that's the least interesting difference between them.&lt;/p&gt;

&lt;p&gt;Here's the direct answer: the tools differ less on file size than on where your images get processed and what you pay. TinyPNG uploads your files to its servers and charges a subscription (Web Pro is $3.25/month billed annually — $39/year, verified on their pricing page today). Browser-local tools like Squoosh and SnapShrink process everything on your device. I build &lt;a href="https://getsnapshrink.com/" rel="noopener noreferrer"&gt;SnapShrink&lt;/a&gt;, a batch image compressor that runs 100% in the browser, and I'll tell you exactly where TinyPNG still wins. If you handle client photos, ID scans, or unreleased work, the privacy angle matters more than a 5% size difference, and almost nobody writes about it.&lt;/p&gt;

&lt;p&gt;&lt;a href="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%2Farticles%2F4j193sfjktrji7f2dgcz.png" class="article-body-image-wrapper"&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%2Farticles%2F4j193sfjktrji7f2dgcz.png" alt="SnapShrink's batch compressor running entirely in the browser — drop images, no upload" width="800" height="416"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  The comparison that actually matters
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;/th&gt;
&lt;th&gt;TinyPNG&lt;/th&gt;
&lt;th&gt;Squoosh&lt;/th&gt;
&lt;th&gt;SnapShrink&lt;/th&gt;
&lt;th&gt;Compressor.io&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Where files are processed&lt;/td&gt;
&lt;td&gt;Their servers&lt;/td&gt;
&lt;td&gt;Your browser&lt;/td&gt;
&lt;td&gt;Your browser&lt;/td&gt;
&lt;td&gt;Their servers&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Free batch limit&lt;/td&gt;
&lt;td&gt;20 images, 5 MB each&lt;/td&gt;
&lt;td&gt;1 image at a time&lt;/td&gt;
&lt;td&gt;10/session, no file cap&lt;/td&gt;
&lt;td&gt;~10/session&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Pricing&lt;/td&gt;
&lt;td&gt;Free tier + Pro/Ultra subscriptions ($39/year Pro)&lt;/td&gt;
&lt;td&gt;Free forever&lt;/td&gt;
&lt;td&gt;$9 one-time&lt;/td&gt;
&lt;td&gt;Free tier + subscription&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;API / WordPress plugin&lt;/td&gt;
&lt;td&gt;Yes, mature&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Target an exact file size&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;td&gt;Yes (type the KB)&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;EXIF stripped&lt;/td&gt;
&lt;td&gt;Server-side&lt;/td&gt;
&lt;td&gt;N/A (local)&lt;/td&gt;
&lt;td&gt;On-device, automatic&lt;/td&gt;
&lt;td&gt;Server-side&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;TinyPNG's free tier is honest: 20 images at once, 5 MB each. The paid product is a subscription — $39/year for Web Pro, $149/year for Ultra. That's a fine model for a server-side tool, because bandwidth and compute cost real money per image. It's just worth asking whether &lt;em&gt;your&lt;/em&gt; use case needs a server at all.&lt;/p&gt;

&lt;h2&gt;
  
  
  How does in-browser compression actually work?
&lt;/h2&gt;

&lt;p&gt;No magic, and no server: the browser reads your files with the File API, encodes them in a Web Worker (so the tab stays responsive), and hands you the bytes back. The network is never involved — your CPU does the work your laptop was already going to do.&lt;/p&gt;

&lt;p&gt;The quality difference people worry about is real but small. Browser canvas encoders are a bit less efficient than TinyPNG's proprietary quantizer at maximum compression, but encoder choice matters less than &lt;em&gt;your&lt;/em&gt; settings. On a 3000×2000 test photo I measured, JPEG quality 80 came out ~42% smaller than quality 95 with no visible difference at normal viewing distance — and switching the same photo to &lt;a href="https://getsnapshrink.com/webp-converter/" rel="noopener noreferrer"&gt;WebP&lt;/a&gt; at quality 80 cut the file to less than half the JPEG. Quality level, dimensions, and format dwarf the tool-to-tool gap.&lt;/p&gt;

&lt;h2&gt;
  
  
  How can you verify a compressor really keeps your files local?
&lt;/h2&gt;

&lt;p&gt;Don't trust privacy policies — test them. This 30-second check works on every compressor on the market, including mine:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Open any compressor, press F12 → Network tab.&lt;/li&gt;
&lt;li&gt;Drop in photos, compress.&lt;/li&gt;
&lt;li&gt;Filter for uploads (POST/PUT with file bodies).&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;With a browser-local tool you'll see zero — because there are none to see. Run the same test on a server-side compressor and watch the difference.&lt;/p&gt;

&lt;p&gt;There's a second angle nobody mentions: EXIF data. Phone photos carry GPS coordinates, timestamps, device info. Upload that to a server compressor and the metadata travels with the file — you're trusting their pipeline to strip it. Local tools strip it on your device before anything could leave. (I wrote up &lt;a href="https://getsnapshrink.com/blog/strip-metadata-from-photos/" rel="noopener noreferrer"&gt;why that matters&lt;/a&gt; separately.)&lt;/p&gt;

&lt;h2&gt;
  
  
  When should you stick with TinyPNG?
&lt;/h2&gt;

&lt;p&gt;Plenty of cases where I'd pick TinyPNG myself:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;You need compression inside an automated workflow — build pipeline, CMS, upload endpoint. TinyPNG's API is built for exactly that; browser tools are manual.&lt;/li&gt;
&lt;li&gt;You use the WordPress plugin. Mature, set-and-forget.&lt;/li&gt;
&lt;li&gt;You want their specific PNG quantization. For aggressive PNG size reduction it's still excellent.&lt;/li&gt;
&lt;li&gt;You're compressing 1–5 images occasionally and don't care about uploads or subscriptions.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The honest version: these tools overlap but aren't identical. TinyPNG has the ecosystem. Browser-local tools have the privacy model and (in our case) the pricing model.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why can a browser tool charge $9 once while TinyPNG charges $39/year?
&lt;/h2&gt;

&lt;p&gt;Because the cost structures are completely different. Server-side tools pay for bandwidth and compute on every single image — subscriptions make sense for them. A browser tool's marginal cost per image is ~zero after the page loads, so charging monthly rent for it is a business choice, not a technical necessity.&lt;/p&gt;

&lt;p&gt;That's the whole argument for $9 once: pay through Dodo Payments, get a license key by email, paste it in, done. Offline verification, no account, 14-day money-back guarantee.&lt;/p&gt;

&lt;p&gt;Limitations, stated plainly: no API, no WordPress plugin, no AVIF output in v1, 10 free images per session. If any of those are your workflow, TinyPNG or Squoosh is the better pick.&lt;/p&gt;

&lt;h2&gt;
  
  
  FAQ
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Is SnapShrink actually free?
&lt;/h3&gt;

&lt;p&gt;The first 10 images per session are free, no account needed. After that it's a $9 one-time payment for unlimited use — not a subscription. There's a 14-day money-back guarantee, and the license is verified offline, so the tool keeps working even without an account system.&lt;/p&gt;

&lt;h3&gt;
  
  
  Does browser compression match TinyPNG's quality?
&lt;/h3&gt;

&lt;p&gt;Close enough that your settings matter more than your tool. TinyPNG's quantizer has a small edge on maximum PNG compression, but quality level, dimensions, and format choice (especially WebP) move file size far more than encoder choice. My own test: JPEG quality 80 vs 95 on the same photo — 42% smaller, no visible difference.&lt;/p&gt;

&lt;h3&gt;
  
  
  What happens to EXIF data in my photos?
&lt;/h3&gt;

&lt;p&gt;It's stripped on your device, automatically, before anything could leave — because nothing ever leaves. With server-side compressors, your GPS coordinates and timestamps travel with the upload and you're trusting their pipeline to strip them. I wrote a &lt;a href="https://getsnapshrink.com/blog/strip-metadata-from-photos/" rel="noopener noreferrer"&gt;separate guide on stripping metadata from photos&lt;/a&gt; if you want the full picture.&lt;/p&gt;

&lt;h3&gt;
  
  
  Can I hit an exact file size, like under 100KB?
&lt;/h3&gt;

&lt;p&gt;Yes — that's the one thing most compressors can't do. Instead of guessing the quality slider, you &lt;a href="https://getsnapshrink.com/compress-image-to-exact-kb/" rel="noopener noreferrer"&gt;compress an image to an exact file size&lt;/a&gt; by typing the target KB, and the tool finds the quality setting that fits at or under it.&lt;/p&gt;

&lt;p&gt;&lt;a href="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%2Farticles%2Fnswnxrhu9bwuqzt5hiia.png" class="article-body-image-wrapper"&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%2Farticles%2Fnswnxrhu9bwuqzt5hiia.png" alt="Type a target KB value and the tool finds the quality setting that fits under it" width="800" height="416"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;p&gt;&lt;em&gt;The longer version with the full comparison table and decision matrix lives on the blog: &lt;a href="https://getsnapshrink.com/blog/tinypng-alternative-pay-once/" rel="noopener noreferrer"&gt;TinyPNG Alternative You Pay Once ($9)&lt;/a&gt;. Try the tool free — &lt;a href="https://getsnapshrink.com/app/" rel="noopener noreferrer"&gt;getsnapshrink.com/app&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>webperf</category>
      <category>privacy</category>
      <category>webdev</category>
      <category>images</category>
    </item>
    <item>
      <title>Stop Guessing the Quality Slider — Binary-Searching JPEG Quality for Exact File Sizes</title>
      <dc:creator>Nawal Shrestha</dc:creator>
      <pubDate>Tue, 06 Oct 2026 12:19:43 +0000</pubDate>
      <link>https://dev.to/nawalshrestha/stop-guessing-the-quality-slider-binary-searching-jpeg-quality-for-exact-file-sizes-4g53</link>
      <guid>https://dev.to/nawalshrestha/stop-guessing-the-quality-slider-binary-searching-jpeg-quality-for-exact-file-sizes-4g53</guid>
      <description>&lt;p&gt;Here's a UX problem every image tool punts on: the user doesn't want "quality 80". They want "under 100KB" — because a form said so. The quality slider is the tool's internal machinery exposed as UI. Users shouldn't have to learn your encoder's quality curve.&lt;/p&gt;

&lt;p&gt;In &lt;a href="https://getsnapshrink.com/compress-image-to-exact-kb/" rel="noopener noreferrer"&gt;SnapShrink&lt;/a&gt; I built Target KB mode: type &lt;code&gt;20&lt;/code&gt;, get a file at or under 20KB. Here's the approach.&lt;/p&gt;

&lt;h2&gt;
  
  
  The algorithm
&lt;/h2&gt;

&lt;p&gt;It's a binary search over the quality parameter:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Set bounds: quality 1–100 (or your encoder's range).&lt;/li&gt;
&lt;li&gt;Encode at mid quality, measure the output bytes.&lt;/li&gt;
&lt;li&gt;If over target, search the lower half; if under, search the upper half — keeping the best valid result.&lt;/li&gt;
&lt;li&gt;~7 iterations converges. Each iteration is a fast in-memory encode; no network involved.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The key detail: &lt;strong&gt;quality is searched first, dimensions last.&lt;/strong&gt; Only if quality=1 still overshoots do you downscale slightly and re-run the search. Most photos hit common caps (20/50/100KB) with dimensions untouched, which is what users expect — they asked for a size, not a resize.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why this matters more than it sounds
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Government and exam portals (India's UPSC forms: 20–300KB caps) reject oversized uploads with zero guidance. "Type the number" beats a slider every time.&lt;/li&gt;
&lt;li&gt;It composes with batch: set the target once, every file in the batch gets its own binary search, download as ZIP.&lt;/li&gt;
&lt;li&gt;It works client-side. The encodes are cheap enough to run in a Web Worker without blocking the page.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  The honest edge cases
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Tiny targets on huge photos will visibly degrade — that's physics, not a bug. Showing the achieved size when the target is unreachable beats silently overshooting.&lt;/li&gt;
&lt;li&gt;PNGs with sharp text compress differently than photos; the search handles both because it measures actual bytes, not estimates.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If you maintain an image tool, consider exposing the target instead of (or alongside) the slider. Users think in file sizes. Meet them there.&lt;/p&gt;

&lt;p&gt;Live at &lt;a href="https://getsnapshrink.com/compress-image-to-exact-kb/" rel="noopener noreferrer"&gt;getsnapshrink.com/compress-image-to-exact-kb/&lt;/a&gt; — first 10 images per session free, everything runs in the browser. The same engine also powers &lt;a href="https://getsnapshrink.com/heic-to-jpg/" rel="noopener noreferrer"&gt;HEIC→JPG&lt;/a&gt; and &lt;a href="https://getsnapshrink.com/avif-to-jpg/" rel="noopener noreferrer"&gt;AVIF→JPG&lt;/a&gt; conversion — new input formats turned out to be just a decode step.&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>javascript</category>
      <category>images</category>
      <category>algorithms</category>
    </item>
    <item>
      <title>I Added Client-Side HEIC to JPG Conversion to My Image Tool — No Server, No Upload</title>
      <dc:creator>Nawal Shrestha</dc:creator>
      <pubDate>Tue, 06 Oct 2026 12:18:07 +0000</pubDate>
      <link>https://dev.to/nawalshrestha/i-added-client-side-heic-to-jpg-conversion-to-my-image-tool-no-server-no-upload-46oh</link>
      <guid>https://dev.to/nawalshrestha/i-added-client-side-heic-to-jpg-conversion-to-my-image-tool-no-server-no-upload-46oh</guid>
      <description>&lt;p&gt;Most "free HEIC to JPG" tools work the same way: you upload your iPhone photos to someone's server, it converts them, you download the result. For a format conversion — one of the most local operations imaginable — that's a strange trade.&lt;/p&gt;

&lt;p&gt;I wanted HEIC to JPG support in &lt;a href="https://getsnapshrink.com/heic-to-jpg/" rel="noopener noreferrer"&gt;SnapShrink&lt;/a&gt; (my in-browser batch image compressor) without breaking its core promise: nothing ever uploads. Here's how I did it.&lt;/p&gt;

&lt;h2&gt;
  
  
  The decoder: heic2any, lazy-loaded
&lt;/h2&gt;

&lt;p&gt;Browsers can't decode HEIC natively (unlike AVIF, which Chrome/Edge/Firefox handle via &lt;code&gt;createImageBitmap&lt;/code&gt;). So the conversion needs a real decoder. I used &lt;a href="https://github.com/alexcorvi/heic2any" rel="noopener noreferrer"&gt;heic2any&lt;/a&gt;, pinned to a fixed version, loaded via dynamic &lt;code&gt;import()&lt;/code&gt; &lt;strong&gt;only when a HEIC file is actually dropped&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;That last part matters: the decoder is a chunk of WASM/JS you don't want in the initial bundle for the 95% of users who never touch HEIC. Lazy-loading keeps the first paint fast for everyone.&lt;/p&gt;

&lt;h2&gt;
  
  
  The pipeline
&lt;/h2&gt;

&lt;p&gt;Once decoded, a HEIC file is just pixels — it flows into the exact same pipeline as every other format:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Decode → ImageData/canvas&lt;/li&gt;
&lt;li&gt;Quality slider or Target KB mode (binary-search the quality setting until the output fits)&lt;/li&gt;
&lt;li&gt;Encode to JPG/PNG/WebP, batch, ZIP download&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;No HEIC-specific special cases downstream. That was the whole point of the architecture: new input formats are a decode step, not a new app. AVIF support later followed the same path — &lt;a href="https://getsnapshrink.com/avif-to-jpg/" rel="noopener noreferrer"&gt;same idea, native decode&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  The UX details that matter
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Files get a small "HEIC" badge in the drop list so users can see what was detected.&lt;/li&gt;
&lt;li&gt;A misnamed file (&lt;code&gt;.heic&lt;/code&gt; that's actually a JPEG) gets a clear error instead of a cryptic decoder failure.&lt;/li&gt;
&lt;li&gt;Target KB mode works on HEIC too — type &lt;code&gt;100&lt;/code&gt;, get ≤100KB. This is the feature people actually write in about: forms with hard size caps. (&lt;a href="https://getsnapshrink.com/compress-image-to-exact-kb/" rel="noopener noreferrer"&gt;How it works&lt;/a&gt;.)&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Try it
&lt;/h2&gt;

&lt;p&gt;Drop a real iPhone photo on &lt;a href="https://getsnapshrink.com/heic-to-jpg/" rel="noopener noreferrer"&gt;getsnapshrink.com/heic-to-jpg/&lt;/a&gt; and watch DevTools → Network while it converts. Zero file uploads — that's the entire architecture, and HEIC didn't change it.&lt;/p&gt;

&lt;p&gt;First 10 images per session free, unlimited is a one-time $9. Happy to answer questions about the implementation in the comments.&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>javascript</category>
      <category>images</category>
      <category>privacy</category>
    </item>
    <item>
      <title>Compress Image to 100KB Online — No Upload</title>
      <dc:creator>Nawal Shrestha</dc:creator>
      <pubDate>Sun, 04 Oct 2026 03:58:14 +0000</pubDate>
      <link>https://dev.to/nawalshrestha/compress-image-to-100kb-online-no-upload-9pk</link>
      <guid>https://dev.to/nawalshrestha/compress-image-to-100kb-online-no-upload-9pk</guid>
      <description>&lt;p&gt;Visa portals, exam forms, and job applications all ask for the same thing: a photo under 100KB. Most compressors hand you a quality slider and wish you luck — you export at 60%, check the size, re-export at 50%, check again. Five guesses later you land at 97KB with a photo that looks worse than it needed to.&lt;/p&gt;

&lt;p&gt;There's a better way: &lt;strong&gt;name the size, and let the tool find the best quality that fits it.&lt;/strong&gt; Type &lt;code&gt;100&lt;/code&gt;, get ≤100KB, done — with your file never leaving your device.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why 100KB limits are everywhere
&lt;/h2&gt;

&lt;p&gt;Government and university portals process millions of files. A hard per-file cap keeps storage costs and database rows predictable. A phone photo today is 3–8MB, so "under 100KB" means shrinking it to roughly &lt;strong&gt;2% of its original size&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Common places you'll hit this limit:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Visa and passport applications&lt;/strong&gt; — photo and signature uploads, often capped at 100KB or even 50KB&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Exam and university admission portals&lt;/strong&gt; — scanned documents and photos with per-file caps&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Job applications&lt;/strong&gt; — resume portals that reject oversized profile photos&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Scholarship and KYC forms&lt;/strong&gt; — ID scans that must stay small but readable&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Banking portals&lt;/strong&gt; — document uploads for account opening or loans&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The cap persists because the bottleneck is storage and database row size, not your internet speed. Faster broadband didn't move it; it won't move soon.&lt;/p&gt;

&lt;h2&gt;
  
  
  What 100KB actually looks like: quality vs size
&lt;/h2&gt;

&lt;p&gt;People imagine 100KB means a ruined photo. It depends entirely on dimensions. Here's the relationship, roughly, for a typical phone photo saved as JPEG:&lt;/p&gt;

&lt;p&gt;Source dimensions — Quality 85 — Quality 60 — Quality 40&lt;br&gt;
4000×3000 (12MP) — ~2.5 MB — ~1.2 MB — ~600 KB&lt;br&gt;
2000×1500 — ~700 KB — ~350 KB — ~180 KB&lt;br&gt;
1200×900 — ~280 KB — ~140 KB — ~75 KB&lt;br&gt;
800×600 — ~130 KB — ~65 KB — ~35 KB&lt;br&gt;
&lt;em&gt;Illustrative — actual sizes vary with image complexity. Noisy, detailed photos run heavier.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;The takeaway: &lt;strong&gt;100KB is mostly about resolution, not the quality slider.&lt;/strong&gt; A 1200×900 photo at quality 60 hits ~140KB; drop to 800×600 and you're comfortably under 100KB at decent quality. Anyone telling you to "just lower the quality" on a 12MP original is giving bad advice — resize first, then compress.&lt;/p&gt;

&lt;h2&gt;
  
  
  Type 100, get ≤100KB: how target-size mode works
&lt;/h2&gt;

&lt;p&gt;In SnapShrink you type &lt;code&gt;100&lt;/code&gt; into the target-size box and the engine does the search for you:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Drop your image&lt;/strong&gt; at &lt;a href="https://getsnapshrink.com/app/" rel="noopener noreferrer"&gt;https://getsnapshrink.com/app/&lt;/a&gt;. JPG, PNG, WebP, and GIF accepted.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Type &lt;code&gt;100&lt;/code&gt;&lt;/strong&gt; as the target size in KB and pick your output format (WebP is smallest for photos — but check portal acceptance below).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Binary search on quality.&lt;/strong&gt; The engine encodes at quality 95, then 50, then narrows the range — about 8 encodes — to find the highest quality that lands at or under 100KB.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Downscale fallback.&lt;/strong&gt; If even quality 5 overshoots, the image scales down in ×0.9 steps (never below 320px) and the search repeats.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;You get the result&lt;/strong&gt; with before/after sizes shown. On the rare image where 100KB is truly unreachable, it reports the best effort it managed instead of failing silently.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;It all runs in a background worker in your browser tab, so the page stays responsive. A standard 5MP phone photo typically finishes in under 3 seconds.&lt;/p&gt;

&lt;h2&gt;
  
  
  Which format will the portal accept?
&lt;/h2&gt;

&lt;p&gt;This is where people get burned. You compress a beautiful 80KB WebP, upload it, and the portal rejects it — not for size, but for format. Older government and banking portals often accept &lt;strong&gt;only JPEG&lt;/strong&gt; (sometimes only JPG, not even PNG).&lt;/p&gt;

&lt;p&gt;Your image — Best format — Why&lt;br&gt;
Photo / camera shot — WebP or JPEG — Smallest at a given quality; WebP usually wins ~25%&lt;br&gt;
Screenshot / graphic with text — PNG or WebP — Keeps edges sharp&lt;br&gt;
Scan of a document — WebP or JPEG — Text stays readable far below 100KB in grayscale&lt;br&gt;
Signature on white background — PNG or JPEG — Tiny anyway; JPEG safest for old portals&lt;br&gt;
&lt;strong&gt;Rule: when in doubt, JPEG.&lt;/strong&gt; It's the universally accepted format. Use WebP only when you've confirmed the portal takes it — or when the file is for your own site, not someone else's form.&lt;/p&gt;

&lt;h2&gt;
  
  
  Compress a batch to 100KB
&lt;/h2&gt;

&lt;p&gt;A passport photo, a signature scan, a supporting ID — drop them all at once. SnapShrink's bulk image compressor (&lt;a href="https://getsnapshrink.com/bulk-image-compressor/" rel="noopener noreferrer"&gt;https://getsnapshrink.com/bulk-image-compressor/&lt;/a&gt;) applies the 100KB target to &lt;strong&gt;each file individually&lt;/strong&gt;, because every image needs a different quality level to hit the same cap. When the batch finishes, download everything as one ZIP.&lt;/p&gt;

&lt;p&gt;This beats the one-by-one loop most online tools force on you, and it eliminates the rename-and-organize step — the ZIP keeps your filenames.&lt;/p&gt;

&lt;h2&gt;
  
  
  Compressing from a phone
&lt;/h2&gt;

&lt;p&gt;Identical process in Safari on iOS and Chrome on Android: tap the drop zone, pick from camera roll or files, type &lt;code&gt;100&lt;/code&gt;, download. The file lands in Downloads, ready to attach.&lt;/p&gt;

&lt;p&gt;One iOS wrinkle: phone photos are typically HEIC. Safari converts HEIC to JPEG automatically through the file picker, so SnapShrink receives a JPEG and processes it normally. No manual conversion needed.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why "no upload" matters for document compression
&lt;/h2&gt;

&lt;p&gt;Passport photos, ID scans, and visa applications contain biometric data. Uploading those to a third-party compressor — even one promising deletion — creates a data trail: how long the server &lt;em&gt;actually&lt;/em&gt; retains the file, who can access it, what their breach notification obligations are. You have no visibility into any of that.&lt;/p&gt;

&lt;p&gt;SnapShrink processes images with the browser's Canvas API and a Web Worker. The bytes never leave your device.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Verify it yourself&lt;/strong&gt; — don't take my word for it:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Open the tool (&lt;a href="https://getsnapshrink.com/app/" rel="noopener noreferrer"&gt;https://getsnapshrink.com/app/&lt;/a&gt;) and press F12 → Network tab.&lt;/li&gt;
&lt;li&gt;Compress a photo.&lt;/li&gt;
&lt;li&gt;Look for file uploads in the network log.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;There are none. Thirty seconds, and you've confirmed what no privacy policy can prove for a server-side tool. For documents this sensitive, "trust us" isn't good enough — testable beats promised.&lt;/p&gt;

&lt;p&gt;SnapShrink also strips EXIF metadata (GPS coordinates, device info, timestamps) automatically during compression. Your ID photo shouldn't ship your location history to a portal database.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step by step: compress to 100KB
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;Open the SnapShrink tool (&lt;a href="https://getsnapshrink.com/app/" rel="noopener noreferrer"&gt;https://getsnapshrink.com/app/&lt;/a&gt;) — no signup, no install.&lt;/li&gt;
&lt;li&gt;Drag in your photo (or pick files with the button).&lt;/li&gt;
&lt;li&gt;Type &lt;code&gt;100&lt;/code&gt; in the target-size field. Choose JPEG if the portal is old or unspecified; WebP if confirmed accepted.&lt;/li&gt;
&lt;li&gt;Hit Compress, then download. The file is ≤100KB and ready for the portal.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;First 10 images per session are free. If you process documents regularly, one $9 payment unlocks unlimited use — no subscription.&lt;/p&gt;

&lt;h2&gt;
  
  
  Troubleshooting: when the image won't reach 100KB
&lt;/h2&gt;

&lt;p&gt;Genuinely impossible cases are rare but real. A 320×320px photo that's already 110KB at quality 1 in JPEG has nowhere left to go. In that situation:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Switch to WebP&lt;/strong&gt; — usually smaller than JPEG at the same dimensions (if the portal allows).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Crop tighter&lt;/strong&gt; — border whitespace costs bytes, especially in JPEG.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Resize to the portal's minimum&lt;/strong&gt; — if it says "minimum 200×200px", try exactly 200×200.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Grayscale for documents&lt;/strong&gt; — some portals accept it, and it compresses far more efficiently.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Check the EXIF&lt;/strong&gt; — a 50–200KB metadata payload on an unprocessed phone photo is dead weight; stripping it alone can close the gap.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;SnapShrink always reports the actual output size, so you know exactly where you stand instead of guessing whether a rejection was the size, the format, or the portal being slow.&lt;/p&gt;

&lt;h2&gt;
  
  
  FAQ
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Is my photo uploaded to a server?&lt;/strong&gt;&lt;br&gt;
No. Compression happens entirely in your browser. Open DevTools → Network while compressing — zero file uploads. That's the whole point.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What if my image can't reach 100KB?&lt;/strong&gt;&lt;br&gt;
Rare, but possible with very detailed images at small dimensions. You'll see the smallest size achieved ("best effort") instead of a silent failure.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Which browsers work?&lt;/strong&gt;&lt;br&gt;
Chrome, Edge, Firefox, and Safari handle WebP encoding natively. If yours can't encode WebP, the tool says so and you pick JPEG or PNG instead.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Is there a file size limit?&lt;/strong&gt;&lt;br&gt;
Files up to 50MB accepted. Larger files are skipped with a clear message; the rest of the batch keeps going.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Can I compress multiple images to 100KB at once?&lt;/strong&gt;&lt;br&gt;
Yes — drop the batch, set the target once, download a ZIP. Each image is processed individually to hit the same cap.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;JPEG or WebP for a 100KB target?&lt;/strong&gt;&lt;br&gt;
WebP preserves more quality at 100KB, but old portals may reject it. JPEG when unsure; WebP when confirmed.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;How is this different from Squoosh?&lt;/strong&gt;&lt;br&gt;
Squoosh is excellent for single-image manual tuning. SnapShrink is built for two things Squoosh doesn't do: &lt;strong&gt;batch processing&lt;/strong&gt; and &lt;strong&gt;target-size mode&lt;/strong&gt; — type the cap, get there automatically. One image with pixel-perfect control: Squoosh. A stack of documents with a size cap: SnapShrink.&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>webperf</category>
      <category>tutorial</category>
      <category>privacy</category>
    </item>
  </channel>
</rss>
