<?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>Forem: Shaishav Patel</title>
    <description>The latest articles on Forem by Shaishav Patel (@shaishav_patel_271fdcd61a).</description>
    <link>https://forem.com/shaishav_patel_271fdcd61a</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.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3765357%2F4328a95f-6619-4f38-80e1-8b0865eb2470.jpg</url>
      <title>Forem: Shaishav Patel</title>
      <link>https://forem.com/shaishav_patel_271fdcd61a</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/shaishav_patel_271fdcd61a"/>
    <language>en</language>
    <item>
      <title>Embedding UPI QR Codes in PDF Invoices with qr-code-styling and pdf-lib in Next.js</title>
      <dc:creator>Shaishav Patel</dc:creator>
      <pubDate>Mon, 11 May 2026 15:14:37 +0000</pubDate>
      <link>https://forem.com/shaishav_patel_271fdcd61a/embedding-upi-qr-codes-in-pdf-invoices-with-qr-code-styling-and-pdf-lib-in-nextjs-4jeo</link>
      <guid>https://forem.com/shaishav_patel_271fdcd61a/embedding-upi-qr-codes-in-pdf-invoices-with-qr-code-styling-and-pdf-lib-in-nextjs-4jeo</guid>
      <description>&lt;h2&gt;
  
  
  The Problem
&lt;/h2&gt;

&lt;p&gt;Our &lt;a href="https://ultimatetools.io/tools/misc-tools/invoice-generator/" rel="noopener noreferrer"&gt;Invoice Generator&lt;/a&gt; already used &lt;strong&gt;pdf-lib&lt;/strong&gt; to generate PDFs client-side and &lt;strong&gt;qr-code-styling&lt;/strong&gt; for QR generation elsewhere in the app. Adding a UPI payment QR to Indian invoices seemed straightforward — but there's one non-obvious step: &lt;code&gt;qr-code-styling&lt;/code&gt; produces a &lt;code&gt;Blob&lt;/code&gt;, and &lt;code&gt;pdf-lib&lt;/code&gt; needs a &lt;code&gt;Uint8Array&lt;/code&gt;. You can't just pass one to the other.&lt;/p&gt;

&lt;p&gt;This post covers the exact pipeline: UPI deep link → QR PNG blob → &lt;code&gt;ArrayBuffer&lt;/code&gt; → &lt;code&gt;Uint8Array&lt;/code&gt; → pdf-lib &lt;code&gt;embedPng&lt;/code&gt; → page render.&lt;/p&gt;




&lt;h2&gt;
  
  
  The UPI Deep Link Format
&lt;/h2&gt;

&lt;p&gt;Every UPI app in India (GPay, PhonePe, Paytm, BHIM, all bank apps) understands a standard deep link format:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;upi://pay?pa=&amp;lt;upi-id&amp;gt;&amp;amp;am=&amp;lt;amount&amp;gt;&amp;amp;cu=INR
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;pa&lt;/code&gt; = payee address (your UPI ID: &lt;code&gt;name@bank&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;am&lt;/code&gt; = amount in rupees, two decimal places&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;cu&lt;/code&gt; = currency code (always &lt;code&gt;INR&lt;/code&gt;)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;When a UPI app scans a QR encoding this URL, it opens the payment confirmation screen with all fields pre-filled. The user just confirms with PIN or biometric.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;upiUrl&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;`upi://pay?pa=&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nf"&gt;encodeURIComponent&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;upiId&lt;/span&gt;&lt;span class="p"&gt;)}&lt;/span&gt;&lt;span class="s2"&gt;&amp;amp;am=&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;total&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;toFixed&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;)}&lt;/span&gt;&lt;span class="s2"&gt;&amp;amp;cu=INR`&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;encodeURIComponent&lt;/code&gt; on the UPI ID handles edge cases like &lt;code&gt;+&lt;/code&gt; signs in some UPI IDs.&lt;/p&gt;




&lt;h2&gt;
  
  
  Generating the QR as a PNG Blob
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;qr-code-styling&lt;/code&gt; is a browser-safe QR library with styling options. It's already in the project for other QR features, so no extra install. Key method: &lt;code&gt;getRawData('png')&lt;/code&gt; returns a &lt;code&gt;Promise&amp;lt;Blob | null&amp;gt;&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;QRCodeStyling&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="k"&gt;import&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;qr-code-styling&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)).&lt;/span&gt;&lt;span class="k"&gt;default&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;qr&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;QRCodeStyling&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;width&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;150&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;height&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;150&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;data&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;upiUrl&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;dotsOptions&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;square&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;#000000&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="na"&gt;backgroundOptions&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;#ffffff&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="na"&gt;qrOptions&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;errorCorrectionLevel&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;M&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;qrBlob&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;qr&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getRawData&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;png&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We use a dynamic import (&lt;code&gt;await import(...)&lt;/code&gt;) because this runs inside an async PDF generation function. The library is only loaded when an India invoice with a UPI ID is actually downloaded — no cost for other regions.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;errorCorrectionLevel: "M"&lt;/code&gt; (15% recovery) is the right balance for UPI QRs. The &lt;code&gt;upi://&lt;/code&gt; URL is short enough that even "M" keeps the QR simple and scannable at small sizes.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Bridge: Blob → Uint8Array
&lt;/h2&gt;

&lt;p&gt;This is the step that isn't obvious. &lt;code&gt;pdf-lib&lt;/code&gt;'s &lt;code&gt;embedPng&lt;/code&gt; needs a &lt;code&gt;Uint8Array&lt;/code&gt;, not a &lt;code&gt;Blob&lt;/code&gt;. The path is:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Blob → ArrayBuffer (via .arrayBuffer()) → Uint8Array
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;qrBlob&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;arrayBuffer&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;qrBlob&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nx"&gt;Blob&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;arrayBuffer&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;pngBytes&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Uint8Array&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;arrayBuffer&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;qrImage&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;pdfDoc&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;embedPng&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;pngBytes&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="c1"&gt;// ...&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;as Blob&lt;/code&gt; cast is needed because TypeScript types &lt;code&gt;getRawData&lt;/code&gt; return as &lt;code&gt;Blob | null | undefined&lt;/code&gt; depending on the version — the null guard above already handles the null case.&lt;/p&gt;




&lt;h2&gt;
  
  
  Positioning the QR on the PDF Page
&lt;/h2&gt;

&lt;p&gt;Our A4 page is 595×842 points. We fix the QR in the &lt;strong&gt;bottom-right corner&lt;/strong&gt; so it never overlaps the invoice content regardless of how many line items are on the page.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;qrSize&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;90&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;          &lt;span class="c1"&gt;// 90pt ≈ 32mm — scannable at that size&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;qrX&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;width&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="mi"&gt;40&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="nx"&gt;qrSize&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;   &lt;span class="c1"&gt;// 40pt right margin&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;qrY&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;36&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;             &lt;span class="c1"&gt;// 36pt from bottom&lt;/span&gt;

&lt;span class="nx"&gt;page&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;drawImage&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;qrImage&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;x&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;qrX&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;y&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;qrY&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;width&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;qrSize&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;height&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;qrSize&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In pdf-lib, &lt;code&gt;y=0&lt;/code&gt; is the &lt;strong&gt;bottom&lt;/strong&gt; of the page (not the top). So &lt;code&gt;y: 36&lt;/code&gt; places the QR near the bottom edge.&lt;/p&gt;

&lt;p&gt;Then add the label above and the UPI ID below:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Label above&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;scanLabel&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Scan to Pay (UPI)&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;scanW&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;font&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;widthOfTextAtSize&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;scanLabel&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;7&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nx"&gt;page&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;drawText&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;scanLabel&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;x&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;qrX&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;qrSize&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="nx"&gt;scanW&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;y&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;qrY&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;qrSize&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;size&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;7&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;font&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;rgb&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mf"&gt;0.4&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mf"&gt;0.4&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mf"&gt;0.4&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="c1"&gt;// UPI ID below&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;upiLabel&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;upiId&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;slice&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;32&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// truncate long IDs&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;upiW&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;font&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;widthOfTextAtSize&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;upiLabel&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;6&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nx"&gt;page&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;drawText&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;upiLabel&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;x&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;qrX&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;qrSize&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="nx"&gt;upiW&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;y&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;qrY&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;size&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;6&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;font&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;rgb&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mf"&gt;0.4&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mf"&gt;0.4&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mf"&gt;0.4&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;(qrSize - textWidth) / 2&lt;/code&gt; centers the text under/over the QR. We use 7pt for the label (readable but unobtrusive) and 6pt for the ID (secondary info).&lt;/p&gt;




&lt;h2&gt;
  
  
  Wrapping in Error Handling
&lt;/h2&gt;

&lt;p&gt;QR generation involves async operations that could fail (library load error, blob generation error, embedPng error). Wrapping in try/catch means a QR failure never blocks the PDF download:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;state&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;region&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;India&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nx"&gt;state&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;upiId&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;try&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// ... full QR generation and embedding pipeline&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;catch&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// skip QR silently — PDF still downloads without it&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  Full Snippet
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Inside your async generatePDF function, before pdfDoc.save()&lt;/span&gt;

&lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;state&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;region&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;India&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nx"&gt;state&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;upiId&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;try&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;QRCodeStyling&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="k"&gt;import&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;qr-code-styling&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)).&lt;/span&gt;&lt;span class="k"&gt;default&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;upiUrl&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;`upi://pay?pa=&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nf"&gt;encodeURIComponent&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;state&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;upiId&lt;/span&gt;&lt;span class="p"&gt;)}&lt;/span&gt;&lt;span class="s2"&gt;&amp;amp;am=&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;total&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;toFixed&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;)}&lt;/span&gt;&lt;span class="s2"&gt;&amp;amp;cu=INR`&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;qr&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;QRCodeStyling&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
      &lt;span class="na"&gt;width&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;150&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;height&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;150&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;data&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;upiUrl&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;dotsOptions&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;square&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;#000000&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
      &lt;span class="na"&gt;backgroundOptions&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;#ffffff&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
      &lt;span class="na"&gt;qrOptions&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;errorCorrectionLevel&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;M&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="p"&gt;});&lt;/span&gt;

    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;qrBlob&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;qr&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getRawData&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;png&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;qrBlob&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;arrayBuffer&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;qrBlob&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nx"&gt;Blob&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;arrayBuffer&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
      &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;qrImage&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;pdfDoc&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;embedPng&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Uint8Array&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;arrayBuffer&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;

      &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;qrSize&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;90&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
      &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;qrX&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;width&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="mi"&gt;40&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="nx"&gt;qrSize&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
      &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;qrY&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;36&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

      &lt;span class="nx"&gt;page&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;drawImage&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;qrImage&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;x&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;qrX&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;y&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;qrY&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;width&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;qrSize&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;height&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;qrSize&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;

      &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;scanLabel&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Scan to Pay (UPI)&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
      &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;scanW&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;font&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;widthOfTextAtSize&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;scanLabel&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;7&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="nx"&gt;page&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;drawText&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;scanLabel&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="na"&gt;x&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;qrX&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;qrSize&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="nx"&gt;scanW&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;y&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;qrY&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;qrSize&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;size&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;7&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;font&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;rgb&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mf"&gt;0.4&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mf"&gt;0.4&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mf"&gt;0.4&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
      &lt;span class="p"&gt;});&lt;/span&gt;

      &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;upiLabel&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;state&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;upiId&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;slice&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;32&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;upiW&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;font&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;widthOfTextAtSize&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;upiLabel&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;6&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="nx"&gt;page&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;drawText&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;upiLabel&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="na"&gt;x&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;qrX&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;qrSize&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="nx"&gt;upiW&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;y&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;qrY&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;size&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;6&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;font&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;rgb&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mf"&gt;0.4&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mf"&gt;0.4&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mf"&gt;0.4&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
      &lt;span class="p"&gt;});&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;catch&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="cm"&gt;/* skip QR on error */&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;pdfBytes&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;pdfDoc&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;save&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  Live Example
&lt;/h2&gt;

&lt;p&gt;The full invoice generator (India region with UPI QR, plus Canada HST, Australia GST, UK VAT, EU VAT, USA sales tax) is live at the &lt;a href="https://ultimatetools.io/tools/misc-tools/invoice-generator/" rel="noopener noreferrer"&gt;Invoice Generator&lt;/a&gt; — free, no signup, browser-only.&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>nextjs</category>
      <category>webdev</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>How to Create a Free GST Invoice Online — With UPI QR Code, No Signup</title>
      <dc:creator>Shaishav Patel</dc:creator>
      <pubDate>Mon, 11 May 2026 15:14:27 +0000</pubDate>
      <link>https://forem.com/shaishav_patel_271fdcd61a/how-to-create-a-free-gst-invoice-online-with-upi-qr-code-no-signup-4516</link>
      <guid>https://forem.com/shaishav_patel_271fdcd61a/how-to-create-a-free-gst-invoice-online-with-upi-qr-code-no-signup-4516</guid>
      <description>&lt;p&gt;If you're a freelancer or small business in India, you need GST invoices that:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Show CGST + SGST (or IGST for inter-state) correctly&lt;/li&gt;
&lt;li&gt;Include your GSTIN and HSN/SAC codes&lt;/li&gt;
&lt;li&gt;Have a way for clients to pay you without you chasing them&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Most free invoice tools handle the first two badly and ignore the third entirely. This post covers a browser-based tool that gets all three right — including a UPI QR code printed directly on the PDF.&lt;/p&gt;




&lt;h2&gt;
  
  
  What the Tool Does
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://ultimatetools.io/tools/misc-tools/invoice-generator/" rel="noopener noreferrer"&gt;UltimateTools Invoice Generator&lt;/a&gt; is a free, browser-based GST invoice maker. No account. No subscription. Your invoice data never leaves your device — the PDF generates entirely in your browser.&lt;/p&gt;

&lt;p&gt;Key features for Indian invoices:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;CGST + SGST split&lt;/strong&gt; — enter your GST rate once, the tool splits it (e.g. 18% → 9% CGST + 9% SGST shown as two separate lines)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;IGST mode&lt;/strong&gt; — toggle for inter-state transactions (single IGST line instead of CGST+SGST)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;GSTIN field&lt;/strong&gt; — shown in the sender block on the PDF&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;HSN/SAC codes&lt;/strong&gt; — per line item column on the invoice table&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;UPI QR code&lt;/strong&gt; — scannable QR in the bottom-right corner of the PDF, pre-loaded with your UPI ID and the exact invoice total&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Step-by-Step: Create a GST Invoice
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Step 1 — Open the tool and select India
&lt;/h3&gt;

&lt;p&gt;Go to the &lt;a href="https://ultimatetools.io/tools/misc-tools/invoice-generator/" rel="noopener noreferrer"&gt;Invoice Generator&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The India region (🇮🇳) is selected by default. The form shows Indian-specific fields: GSTIN, HSN/SAC, CGST/SGST toggle.&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 2 — Fill in your business details
&lt;/h3&gt;

&lt;p&gt;In the &lt;strong&gt;From&lt;/strong&gt; section:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Business name&lt;/li&gt;
&lt;li&gt;Address&lt;/li&gt;
&lt;li&gt;GSTIN (e.g. &lt;code&gt;27AABCU9603R1ZX&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;Email (optional)&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Step 3 — Fill in client details
&lt;/h3&gt;

&lt;p&gt;In the &lt;strong&gt;Bill To&lt;/strong&gt; section:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Client name&lt;/li&gt;
&lt;li&gt;Client address&lt;/li&gt;
&lt;li&gt;Client GSTIN (optional — required if they want to claim ITC)&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Step 4 — Choose tax type
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;CGST + SGST&lt;/strong&gt; — use this when you and your client are in the same state. The tool automatically splits the rate (18% → 9% CGST + 9% SGST).&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;IGST&lt;/strong&gt; — use this when you and your client are in different states. Shows as a single IGST line at the full rate.&lt;/p&gt;

&lt;p&gt;Enter your GST rate percentage. Common rates: 5%, 12%, 18%, 28%.&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 5 — Add line items
&lt;/h3&gt;

&lt;p&gt;Each row has: Description | HSN/SAC code | Qty | Rate | Amount&lt;/p&gt;

&lt;p&gt;The tool calculates the line total and applies tax to the subtotal. Supports multiple items.&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 6 — Add your UPI ID
&lt;/h3&gt;

&lt;p&gt;There's a &lt;strong&gt;UPI ID&lt;/strong&gt; field below the payment details section. Enter your UPI ID (format: &lt;code&gt;name@bankname&lt;/code&gt; or &lt;code&gt;9876543210@upi&lt;/code&gt;).&lt;/p&gt;

&lt;p&gt;This is what gets encoded in the QR code on the PDF.&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 7 — Download
&lt;/h3&gt;

&lt;p&gt;Click &lt;strong&gt;Download Invoice&lt;/strong&gt;. The PDF opens for download — no upload, no server, instant.&lt;/p&gt;




&lt;h2&gt;
  
  
  What the PDF Looks Like
&lt;/h2&gt;

&lt;p&gt;The downloaded invoice includes:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Your business name and GSTIN at the top&lt;/li&gt;
&lt;li&gt;Invoice number, date, and due date&lt;/li&gt;
&lt;li&gt;Client details&lt;/li&gt;
&lt;li&gt;Line items table with HSN/SAC codes&lt;/li&gt;
&lt;li&gt;Subtotal → CGST line → SGST line → Total&lt;/li&gt;
&lt;li&gt;Notes and payment terms sections&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;UPI QR code&lt;/strong&gt; in the bottom-right corner with "Scan to Pay (UPI)" label and your UPI ID printed below it&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The QR encodes a UPI deep link: &lt;code&gt;upi://pay?pa=yourname@upi&amp;amp;am=12400.00&amp;amp;cu=INR&lt;/code&gt;. Every UPI app (GPay, PhonePe, Paytm, BHIM, bank apps) opens the payment screen with your ID and the exact amount pre-filled when scanned.&lt;/p&gt;




&lt;h2&gt;
  
  
  CGST vs SGST vs IGST — Quick Reference
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Transaction type&lt;/th&gt;
&lt;th&gt;Tax type&lt;/th&gt;
&lt;th&gt;Example at 18%&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Seller and buyer in same state&lt;/td&gt;
&lt;td&gt;CGST + SGST&lt;/td&gt;
&lt;td&gt;9% CGST + 9% SGST&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Seller and buyer in different states&lt;/td&gt;
&lt;td&gt;IGST&lt;/td&gt;
&lt;td&gt;18% IGST&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Export outside India&lt;/td&gt;
&lt;td&gt;Zero-rated (exempt)&lt;/td&gt;
&lt;td&gt;0%&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;




&lt;h2&gt;
  
  
  Invoice Number Auto-Increment
&lt;/h2&gt;

&lt;p&gt;The tool remembers your last invoice number in your browser's localStorage and suggests the next one automatically. You can override it at any time.&lt;/p&gt;

&lt;p&gt;Format: &lt;code&gt;INV-001&lt;/code&gt;, &lt;code&gt;INV-002&lt;/code&gt;, etc. — or set your own like &lt;code&gt;FY26-001&lt;/code&gt;.&lt;/p&gt;




&lt;h2&gt;
  
  
  Download and Share
&lt;/h2&gt;

&lt;p&gt;Once downloaded, the PDF is a standard file you can:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Email as an attachment&lt;/li&gt;
&lt;li&gt;Share via WhatsApp (works on mobile)&lt;/li&gt;
&lt;li&gt;Print and hand over&lt;/li&gt;
&lt;li&gt;Save to Google Drive or Dropbox&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The UPI QR works whether the client opens the PDF on their laptop (they point their phone camera at the screen) or on mobile (they can share it to another device or screenshot it).&lt;/p&gt;




&lt;h2&gt;
  
  
  Free, Always
&lt;/h2&gt;

&lt;p&gt;No signup. No credit card. No watermark. No "free plan" with limits.&lt;/p&gt;

&lt;p&gt;Create your first GST invoice with UPI QR: &lt;a href="https://ultimatetools.io/tools/misc-tools/invoice-generator/" rel="noopener noreferrer"&gt;Invoice Generator&lt;/a&gt;&lt;/p&gt;

</description>
      <category>india</category>
      <category>freelancing</category>
      <category>tools</category>
      <category>productivity</category>
    </item>
    <item>
      <title>Generate Bulk QR Codes From a CSV File — Free, No Signup, ZIP Download</title>
      <dc:creator>Shaishav Patel</dc:creator>
      <pubDate>Mon, 11 May 2026 15:08:22 +0000</pubDate>
      <link>https://forem.com/shaishav_patel_271fdcd61a/generate-bulk-qr-codes-from-a-csv-file-free-no-signup-zip-download-5ap4</link>
      <guid>https://forem.com/shaishav_patel_271fdcd61a/generate-bulk-qr-codes-from-a-csv-file-free-no-signup-zip-download-5ap4</guid>
      <description>&lt;p&gt;Generating QR codes one at a time works fine for a handful. For 50, 200, or 500 — it's a time sink you don't need.&lt;/p&gt;

&lt;p&gt;The &lt;a href="https://ultimatetools.io/tools/misc-tools/bulk-qr-code-generator/" rel="noopener noreferrer"&gt;Bulk QR Code Generator&lt;/a&gt; takes a CSV file, generates one QR code per row, and downloads everything as a ZIP. No account, no upload limit up to 500 codes, free.&lt;/p&gt;

&lt;p&gt;Here's how to use it.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 1 — Prepare your CSV
&lt;/h2&gt;

&lt;p&gt;Open Excel, Google Sheets, or any text editor. Create one column of values — one per row. No headers needed.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;https://yoursite.com/product/001
https://yoursite.com/product/002
https://yoursite.com/product/003
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Save as &lt;code&gt;.csv&lt;/code&gt;. That's your entire input file.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 2 — Upload and generate
&lt;/h2&gt;

&lt;p&gt;Open the &lt;a href="https://ultimatetools.io/tools/misc-tools/bulk-qr-code-generator/" rel="noopener noreferrer"&gt;Bulk QR Code Generator&lt;/a&gt; and upload your CSV. The tool reads every row and previews the count immediately.&lt;/p&gt;

&lt;p&gt;Click &lt;strong&gt;Generate&lt;/strong&gt;. Each row becomes one QR code PNG, named after its value so the files are easy to identify and sort.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 3 — Download the ZIP
&lt;/h2&gt;

&lt;p&gt;One click downloads all QR codes in a single ZIP file. Unzip to get individual PNGs ready to use in print, email, or wherever you need them.&lt;/p&gt;

&lt;p&gt;500 codes delivered in the time it would have taken to do 3 manually.&lt;/p&gt;




&lt;h2&gt;
  
  
  What you can encode
&lt;/h2&gt;

&lt;p&gt;Any text content works — not just URLs:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Event tickets&lt;/strong&gt; — unique code per attendee&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Product labels&lt;/strong&gt; — one code per SKU&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Restaurant menus&lt;/strong&gt; — different QR per table or location&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Marketing campaigns&lt;/strong&gt; — unique tracking URLs per channel&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Staff or student ID badges&lt;/strong&gt; — one code per record&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;WiFi credentials&lt;/strong&gt; — same SSID/password distributed in bulk&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Privacy
&lt;/h2&gt;

&lt;p&gt;Everything runs in your browser. Your CSV is never uploaded to a server — it's parsed client-side using JavaScript. No data leaves your device.&lt;/p&gt;




&lt;h2&gt;
  
  
  When to use single vs bulk
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Need&lt;/th&gt;
&lt;th&gt;Tool&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;1–5 codes with custom style (colour, logo, SVG)&lt;/td&gt;
&lt;td&gt;&lt;a href="https://ultimatetools.io/tools/misc-tools/qr-code-generator/" rel="noopener noreferrer"&gt;QR Code Generator&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;6–500 codes from a list, fast&lt;/td&gt;
&lt;td&gt;&lt;a href="https://ultimatetools.io/tools/misc-tools/bulk-qr-code-generator/" rel="noopener noreferrer"&gt;Bulk QR Code Generator&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;The single generator gives you full customisation — colours, styles, logo embedding, SVG output. The bulk generator trades customisation for speed: plain black-and-white PNGs, consistent sizing, ZIP in seconds.&lt;/p&gt;




&lt;h2&gt;
  
  
  Limit
&lt;/h2&gt;

&lt;p&gt;Up to &lt;strong&gt;500 QR codes per batch&lt;/strong&gt;. Need more? Split your CSV into two files and run two batches.&lt;/p&gt;




&lt;p&gt;Generate bulk QR codes free — upload a CSV, download a ZIP: &lt;a href="https://ultimatetools.io/tools/misc-tools/bulk-qr-code-generator/" rel="noopener noreferrer"&gt;Bulk QR Code Generator&lt;/a&gt;&lt;/p&gt;

</description>
      <category>qrcode</category>
      <category>productivity</category>
      <category>tools</category>
      <category>webdev</category>
    </item>
    <item>
      <title>Free Alternatives to Adobe Photoshop for Everyday Image Editing</title>
      <dc:creator>Shaishav Patel</dc:creator>
      <pubDate>Mon, 11 May 2026 10:50:50 +0000</pubDate>
      <link>https://forem.com/shaishav_patel_271fdcd61a/free-alternatives-to-adobe-photoshop-for-everyday-image-editing-550j</link>
      <guid>https://forem.com/shaishav_patel_271fdcd61a/free-alternatives-to-adobe-photoshop-for-everyday-image-editing-550j</guid>
      <description>&lt;p&gt;Adobe Photoshop is $22.99/month. For professional photo retouching, compositing, and print production, it's the industry standard. For the most common image tasks — resize, compress, crop, add a watermark, convert format — you're paying for far more than you need.&lt;/p&gt;

&lt;p&gt;Here are free alternatives organized by what you actually need to do.&lt;/p&gt;




&lt;h2&gt;
  
  
  Resize an image — exact pixel dimensions
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Photoshop approach:&lt;/strong&gt; Image → Image Size → set width/height → Export As.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Free alternative:&lt;/strong&gt; &lt;a href="https://ultimatetools.io/tools/image-tools/resize-image/" rel="noopener noreferrer"&gt;Image Resizer&lt;/a&gt; — set exact width and height in pixels, lock aspect ratio, download. Works in any browser in under 30 seconds. No canvas model, no export dialog — just input dimensions and download.&lt;/p&gt;




&lt;h2&gt;
  
  
  Compress an image — reduce file size
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Photoshop approach:&lt;/strong&gt; File → Export As → set quality slider → Save. Requires knowing the right quality number for a target file size (trial and error).&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Free alternative:&lt;/strong&gt; &lt;a href="https://ultimatetools.io/tools/image-tools/compress-image/" rel="noopener noreferrer"&gt;Image Compressor&lt;/a&gt; — shows before/after file size as you adjust quality. No guessing. The image is processed in your browser with the Canvas API — not uploaded to a server.&lt;/p&gt;




&lt;h2&gt;
  
  
  Crop an image — freehand or aspect ratio locked
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Photoshop approach:&lt;/strong&gt; Crop tool, set ratio in the options bar, drag, confirm.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Free alternative:&lt;/strong&gt; &lt;a href="https://ultimatetools.io/tools/image-tools/crop-image/" rel="noopener noreferrer"&gt;Crop Image&lt;/a&gt; — freehand crop or lock to 1:1, 16:9, 4:3, and other common ratios. Drag handles to adjust. The output is at full original resolution — not downscaled by a canvas layer.&lt;/p&gt;




&lt;h2&gt;
  
  
  Add a watermark — text overlay
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Photoshop approach:&lt;/strong&gt; Add a new text layer, adjust opacity, flatten, export.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Free alternative:&lt;/strong&gt; &lt;a href="https://ultimatetools.io/tools/image-tools/watermark-image/" rel="noopener noreferrer"&gt;Watermark Image&lt;/a&gt; — type your watermark text, set font size, opacity, color, and position, download. No layers to manage.&lt;/p&gt;




&lt;h2&gt;
  
  
  Blur an image or background
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Photoshop approach:&lt;/strong&gt; Filter → Blur → Gaussian Blur (or select background, blur selection).&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Free alternative:&lt;/strong&gt; &lt;a href="https://ultimatetools.io/tools/image-tools/blur-image/" rel="noopener noreferrer"&gt;Blur Image&lt;/a&gt; — apply blur to the full image with a radius slider. For background blurring specifically, Photoshop's AI-assisted "Subject Select" is better — the browser-based alternative doesn't separate foreground from background.&lt;/p&gt;




&lt;h2&gt;
  
  
  Convert image format — JPG, PNG, WebP
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Photoshop approach:&lt;/strong&gt; File → Export As → choose format.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Free alternative:&lt;/strong&gt; &lt;a href="https://ultimatetools.io/tools/image-tools/convert-image/" rel="noopener noreferrer"&gt;Image Converter&lt;/a&gt; — convert between JPEG, PNG, WebP, and other formats. One step.&lt;/p&gt;




&lt;h2&gt;
  
  
  Rotate or flip an image
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Photoshop approach:&lt;/strong&gt; Image → Image Rotation → 90° CW/CCW or arbitrary.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Free alternative:&lt;/strong&gt; &lt;a href="https://ultimatetools.io/tools/image-tools/rotate-image/" rel="noopener noreferrer"&gt;Rotate Image&lt;/a&gt; — rotate 90°/180°/270°, flip horizontal or vertical, download.&lt;/p&gt;




&lt;h2&gt;
  
  
  Where Photoshop has no free browser equivalent
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Layer-based compositing&lt;/strong&gt; — Photoshop's core feature. No browser tool replicates multi-layer editing, blend modes, and non-destructive adjustments. For this, the closest free desktop alternative is GIMP (free, open source).&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;AI-powered tools&lt;/strong&gt; — Generative fill, Neural filters, background replacement using AI subject detection. These require Photoshop's cloud infrastructure.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;RAW photo editing&lt;/strong&gt; — Adjusting RAW camera files with full color control. Photoshop Lightroom is the standard; Darktable is the free desktop alternative.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Batch actions&lt;/strong&gt; — Photoshop Actions can process hundreds of images automatically. For batch resizing or compression of many files, ImageMagick (command line) is the free alternative.&lt;/p&gt;




&lt;h2&gt;
  
  
  Summary: free alternatives by task
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Task&lt;/th&gt;
&lt;th&gt;Free browser tool&lt;/th&gt;
&lt;th&gt;Free desktop app&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Resize&lt;/td&gt;
&lt;td&gt;Image Resizer&lt;/td&gt;
&lt;td&gt;GIMP, IrfanView&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Compress&lt;/td&gt;
&lt;td&gt;Image Compressor&lt;/td&gt;
&lt;td&gt;Squoosh (PWA), GIMP&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Crop&lt;/td&gt;
&lt;td&gt;Crop Image&lt;/td&gt;
&lt;td&gt;GIMP, Paint.NET&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Watermark&lt;/td&gt;
&lt;td&gt;Watermark Image&lt;/td&gt;
&lt;td&gt;GIMP&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Blur&lt;/td&gt;
&lt;td&gt;Blur Image&lt;/td&gt;
&lt;td&gt;GIMP&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Format convert&lt;/td&gt;
&lt;td&gt;Image Converter&lt;/td&gt;
&lt;td&gt;GIMP, IrfanView&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Layer compositing&lt;/td&gt;
&lt;td&gt;❌&lt;/td&gt;
&lt;td&gt;GIMP&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;RAW editing&lt;/td&gt;
&lt;td&gt;❌&lt;/td&gt;
&lt;td&gt;Darktable, RawTherapee&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Batch processing&lt;/td&gt;
&lt;td&gt;❌&lt;/td&gt;
&lt;td&gt;ImageMagick, GIMP scripts&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;For everyday tasks, the browser tools are faster than opening GIMP or any desktop app. The full image toolkit is at &lt;a href="https://ultimatetools.io/tools/image-tools/" rel="noopener noreferrer"&gt;ultimatetools.io/tools/image-tools/&lt;/a&gt; — free, no account, no upload required.&lt;/p&gt;

</description>
      <category>tools</category>
      <category>productivity</category>
      <category>webdev</category>
      <category>javascript</category>
    </item>
    <item>
      <title>How to Go Paperless at Home — Free PDF Tools That Replace Printers and File Cabinets</title>
      <dc:creator>Shaishav Patel</dc:creator>
      <pubDate>Mon, 11 May 2026 10:50:04 +0000</pubDate>
      <link>https://forem.com/shaishav_patel_271fdcd61a/how-to-go-paperless-at-home-free-pdf-tools-that-replace-printers-and-file-cabinets-230p</link>
      <guid>https://forem.com/shaishav_patel_271fdcd61a/how-to-go-paperless-at-home-free-pdf-tools-that-replace-printers-and-file-cabinets-230p</guid>
      <description>&lt;p&gt;Going paperless means replacing physical documents with digital ones. The barriers are usually the same: you still get paper bills, forms, and contracts that need to be signed, filed, and shared. And most PDF software costs money.&lt;/p&gt;

&lt;p&gt;These free browser-based tools from &lt;a href="https://ultimatetools.io/" rel="noopener noreferrer"&gt;Ultimate Tools&lt;/a&gt; handle the most common paperless workflows — all without installing software or uploading documents to a third-party server.&lt;/p&gt;




&lt;h2&gt;
  
  
  Step 1: Scan or photograph physical documents
&lt;/h2&gt;

&lt;p&gt;Before a document can be digital, it needs to be captured. Options:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Phone camera + scanner app&lt;/strong&gt; — apps like Adobe Scan, Microsoft Lens, or Google PhotoScan flatten perspective and produce clean PDF scans&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Flatbed scanner&lt;/strong&gt; — best quality for important documents like passports or contracts&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Phone camera directly&lt;/strong&gt; — good enough for receipts and notes&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The output is usually a JPG or PDF. For JPGs from photos, you can convert them to PDF using the &lt;a href="https://ultimatetools.io/tools/pdf-tools/jpg-to-pdf/" rel="noopener noreferrer"&gt;JPG to PDF tool&lt;/a&gt;.&lt;/p&gt;




&lt;h2&gt;
  
  
  Step 2: Combine documents into organized PDFs
&lt;/h2&gt;

&lt;p&gt;A month of receipts, a collection of pay stubs, or a multi-page form scanned page-by-page — these come in as separate files. The &lt;a href="https://ultimatetools.io/tools/pdf-tools/merge-pdf/" rel="noopener noreferrer"&gt;PDF Merger&lt;/a&gt; combines them into a single organized PDF.&lt;/p&gt;

&lt;p&gt;Drag files to reorder them (receipt chronologically, form pages in sequence), click merge, download. The combined file is what gets stored and shared.&lt;/p&gt;




&lt;h2&gt;
  
  
  Step 3: Compress before storing or emailing
&lt;/h2&gt;

&lt;p&gt;Scanned PDFs are large. A 10-page scanned document from a phone camera can be 20–40MB. Cloud storage has limits, email attachments have caps (25MB for Gmail), and large files are slow to search.&lt;/p&gt;

&lt;p&gt;The &lt;a href="https://ultimatetools.io/tools/pdf-tools/compress-pdf/" rel="noopener noreferrer"&gt;PDF Compressor&lt;/a&gt; reduces scanned PDF size significantly — often 60–80% smaller — without losing legibility. The compression runs in your browser; the document never leaves your device.&lt;/p&gt;




&lt;h2&gt;
  
  
  Step 4: Sign documents digitally — no printer needed
&lt;/h2&gt;

&lt;p&gt;The single biggest reason people still print documents: they need to sign them. The &lt;a href="https://ultimatetools.io/tools/pdf-tools/sign-pdf/" rel="noopener noreferrer"&gt;PDF eSign tool&lt;/a&gt; lets you:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Draw your signature with a mouse or trackpad&lt;/li&gt;
&lt;li&gt;Type your name and use a signature font&lt;/li&gt;
&lt;li&gt;Upload an image of your physical signature&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Add the signature to the PDF, position it on the signature line, download. Send it back by email. No printer, no scanner required.&lt;/p&gt;




&lt;h2&gt;
  
  
  Step 5: Protect sensitive documents with a password
&lt;/h2&gt;

&lt;p&gt;Stored digitally doesn't mean stored safely. Financial documents, tax returns, and medical records stored in cloud drives or emailed should be password protected.&lt;/p&gt;

&lt;p&gt;The &lt;a href="https://ultimatetools.io/tools/pdf-tools/pdf-password-protect/" rel="noopener noreferrer"&gt;PDF Password Protect tool&lt;/a&gt; applies AES-128 encryption in your browser — the document never touches a server. The protected PDF requires the password to open in any PDF reader.&lt;/p&gt;




&lt;h2&gt;
  
  
  Step 6: Extract text from older PDFs
&lt;/h2&gt;

&lt;p&gt;Some scanned PDFs are just images — you can't search or copy text from them. The &lt;a href="https://ultimatetools.io/tools/pdf-tools/pdf-to-text/" rel="noopener noreferrer"&gt;PDF to Text tool&lt;/a&gt; extracts readable text from PDFs. Useful for:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Old utility bills or bank statements you've scanned&lt;/li&gt;
&lt;li&gt;PDFs shared as images (common with government forms)&lt;/li&gt;
&lt;li&gt;Quickly finding a number in a long document&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Complete paperless workflow
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Task&lt;/th&gt;
&lt;th&gt;Paper equivalent&lt;/th&gt;
&lt;th&gt;Tool&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Scan paper document&lt;/td&gt;
&lt;td&gt;Filing cabinet&lt;/td&gt;
&lt;td&gt;Phone scanner app → JPG to PDF&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Combine pages&lt;/td&gt;
&lt;td&gt;Stapler + folder&lt;/td&gt;
&lt;td&gt;PDF Merger&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Reduce storage size&lt;/td&gt;
&lt;td&gt;—&lt;/td&gt;
&lt;td&gt;PDF Compressor&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Sign documents&lt;/td&gt;
&lt;td&gt;Print, sign, scan&lt;/td&gt;
&lt;td&gt;PDF eSign&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Protect sensitive files&lt;/td&gt;
&lt;td&gt;Locked filing cabinet&lt;/td&gt;
&lt;td&gt;PDF Password Protect&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Search document text&lt;/td&gt;
&lt;td&gt;Manual reading&lt;/td&gt;
&lt;td&gt;PDF to Text&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Share documents&lt;/td&gt;
&lt;td&gt;Fax / postal mail&lt;/td&gt;
&lt;td&gt;Email compressed, password-protected PDF&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;




&lt;p&gt;The full PDF toolkit is at &lt;a href="https://ultimatetools.io/tools/pdf-tools/" rel="noopener noreferrer"&gt;ultimatetools.io/tools/pdf-tools/&lt;/a&gt; — merge, compress, sign, protect, convert. All browser-based, all free, no file upload to a third-party server.&lt;/p&gt;

</description>
      <category>tools</category>
      <category>productivity</category>
      <category>webdev</category>
      <category>javascript</category>
    </item>
    <item>
      <title>BankBazaar vs Groww EMI Calculator vs Free Browser Alternative — Which Is Best?</title>
      <dc:creator>Shaishav Patel</dc:creator>
      <pubDate>Mon, 11 May 2026 10:49:58 +0000</pubDate>
      <link>https://forem.com/shaishav_patel_271fdcd61a/bankbazaar-vs-groww-emi-calculator-vs-free-browser-alternative-which-is-best-17k8</link>
      <guid>https://forem.com/shaishav_patel_271fdcd61a/bankbazaar-vs-groww-emi-calculator-vs-free-browser-alternative-which-is-best-17k8</guid>
      <description>&lt;p&gt;EMI calculators are everywhere. BankBazaar and Groww both have them built into their platforms. But both are financial product marketplaces — their calculators are embedded in a flow designed to get you to apply for a loan. That's not always what you want when you're doing a quick calculation.&lt;/p&gt;

&lt;p&gt;Here's how each option compares for someone who just wants accurate EMI math without a sales funnel attached.&lt;/p&gt;




&lt;h2&gt;
  
  
  BankBazaar EMI Calculator
&lt;/h2&gt;

&lt;p&gt;BankBazaar's EMI calculator is well-built. It shows monthly EMI, total interest payable, and total payment amount. You get a basic pie chart showing principal vs interest split.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What's good:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Accurate formula (standard reducing balance EMI)&lt;/li&gt;
&lt;li&gt;Loan type presets (home loan, car loan, personal loan, education loan)&lt;/li&gt;
&lt;li&gt;Shows total interest in rupees&lt;/li&gt;
&lt;li&gt;Relatively clean UI&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Trade-offs:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The calculator is surrounded by loan product ads and "Check Eligibility" CTAs&lt;/li&gt;
&lt;li&gt;Requires navigating their site to find the calculator&lt;/li&gt;
&lt;li&gt;No amortization schedule (month-by-month breakdown)&lt;/li&gt;
&lt;li&gt;No reverse EMI (can't enter "I can afford ₹15,000/month — what loan can I take?")&lt;/li&gt;
&lt;li&gt;Account not required, but the page pushes signup&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Groww EMI Calculator
&lt;/h2&gt;

&lt;p&gt;Groww's EMI calculator is embedded in their investment platform. It has a clean slider-based UI and shows EMI, total interest, and total amount. There's also a simple amortization table.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What's good:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Slider inputs make it easy to adjust amounts interactively&lt;/li&gt;
&lt;li&gt;Shows amortization breakdown by year&lt;/li&gt;
&lt;li&gt;Clean design&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Trade-offs:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Part of the Groww ecosystem — the page has investment product recommendations alongside the calculator&lt;/li&gt;
&lt;li&gt;No reverse EMI calculation&lt;/li&gt;
&lt;li&gt;No loan comparison (can't compare two scenarios side by side)&lt;/li&gt;
&lt;li&gt;Requires Groww account for some features on the platform&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Ultimate Tools EMI Calculator — A neutral alternative
&lt;/h2&gt;

&lt;p&gt;The &lt;a href="https://ultimatetools.io/tools/misc-tools/emi-calculator/" rel="noopener noreferrer"&gt;EMI Calculator&lt;/a&gt; at Ultimate Tools is a standalone tool with no loan products, no ads, and no account.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What it offers:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Standard EMI calculation (reducing balance method)&lt;/li&gt;
&lt;li&gt;Full amortization schedule — every month's principal, interest, and balance&lt;/li&gt;
&lt;li&gt;Reverse EMI — enter your desired monthly payment and get the maximum loan amount&lt;/li&gt;
&lt;li&gt;Prepayment scenarios — see how extra payments reduce total interest&lt;/li&gt;
&lt;li&gt;Loan comparison — compare two loans side by side&lt;/li&gt;
&lt;li&gt;Works for home loans, car loans, personal loans, education loans — any fixed-rate reducing balance loan&lt;/li&gt;
&lt;li&gt;All INR-denominated by default; works for any currency&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;What it doesn't have:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Loan product listings or eligibility checks (this is intentional — it's a calculator, not a marketplace)&lt;/li&gt;
&lt;li&gt;Floating rate EMI projections (fixed rate only)&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Side-by-side comparison
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Feature&lt;/th&gt;
&lt;th&gt;BankBazaar&lt;/th&gt;
&lt;th&gt;Groww&lt;/th&gt;
&lt;th&gt;Ultimate Tools&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Standard EMI calc&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Full amortization table&lt;/td&gt;
&lt;td&gt;❌&lt;/td&gt;
&lt;td&gt;Partial (yearly)&lt;/td&gt;
&lt;td&gt;✅ Monthly&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Reverse EMI&lt;/td&gt;
&lt;td&gt;❌&lt;/td&gt;
&lt;td&gt;❌&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Loan comparison&lt;/td&gt;
&lt;td&gt;❌&lt;/td&gt;
&lt;td&gt;❌&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Prepayment scenarios&lt;/td&gt;
&lt;td&gt;❌&lt;/td&gt;
&lt;td&gt;❌&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Loan product ads&lt;/td&gt;
&lt;td&gt;✅ (many)&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;❌&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Account required&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;td&gt;No (most features)&lt;/td&gt;
&lt;td&gt;❌ Never&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Signup prompts&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;❌&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;




&lt;h2&gt;
  
  
  Which to use
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Use BankBazaar or Groww if:&lt;/strong&gt; You want to compare actual loan products and apply directly — the calculators are entry points to their marketplaces, and that's the primary use case they're built for.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Use Ultimate Tools if:&lt;/strong&gt; You want pure calculation — monthly payment, amortization breakdown, reverse EMI, or loan comparison — without a sales funnel. No account, no ads, no eligibility prompts.&lt;/p&gt;

&lt;p&gt;The EMI calculator is at &lt;a href="https://ultimatetools.io/tools/misc-tools/emi-calculator/" rel="noopener noreferrer"&gt;ultimatetools.io/tools/misc-tools/emi-calculator/&lt;/a&gt; — enter loan amount, interest rate, and tenure; get EMI, full schedule, and reverse calculation. Free, no signup.&lt;/p&gt;

</description>
      <category>tools</category>
      <category>productivity</category>
      <category>webdev</category>
      <category>javascript</category>
    </item>
    <item>
      <title>Best Free QR Code Generators Compared — No Watermark, No Signup, No Limits</title>
      <dc:creator>Shaishav Patel</dc:creator>
      <pubDate>Mon, 11 May 2026 10:48:38 +0000</pubDate>
      <link>https://forem.com/shaishav_patel_271fdcd61a/best-free-qr-code-generators-compared-no-watermark-no-signup-no-limits-144c</link>
      <guid>https://forem.com/shaishav_patel_271fdcd61a/best-free-qr-code-generators-compared-no-watermark-no-signup-no-limits-144c</guid>
      <description>&lt;p&gt;Most QR code generators are free to use but have a catch: watermarks on downloads, signup requirements, file size limits, or paywalled features like bulk generation or custom colors. Here's a straightforward comparison of the best free options.&lt;/p&gt;




&lt;h2&gt;
  
  
  1. Ultimate Tools — Best for bulk and privacy
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://ultimatetools.io/tools/misc-tools/qr-code-generator/" rel="noopener noreferrer"&gt;Ultimate Tools QR Code Generator&lt;/a&gt; and &lt;a href="https://ultimatetools.io/tools/misc-tools/bulk-qr-code-generator/" rel="noopener noreferrer"&gt;Bulk QR Code Generator&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What it offers:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Single QR codes: URL, text, WiFi, vCard, email, phone, SMS&lt;/li&gt;
&lt;li&gt;Bulk generation: up to 500 QR codes from a CSV file&lt;/li&gt;
&lt;li&gt;Custom colors (foreground + background)&lt;/li&gt;
&lt;li&gt;Dot styles: square, rounded, dots&lt;/li&gt;
&lt;li&gt;PNG and SVG export&lt;/li&gt;
&lt;li&gt;No watermark ever&lt;/li&gt;
&lt;li&gt;No account required&lt;/li&gt;
&lt;li&gt;Processes in browser — no file upload&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Best for:&lt;/strong&gt; Anyone who needs clean watermark-free QR codes or needs to generate in bulk from a CSV. Privacy-sensitive use cases where encoded data shouldn't be sent to a server.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Limitation:&lt;/strong&gt; Static QR codes only (no dynamic/trackable QR codes).&lt;/p&gt;




&lt;h2&gt;
  
  
  2. QR Code Monkey — Best free design tool
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;What it offers:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Custom colors, gradients, logo embedding&lt;/li&gt;
&lt;li&gt;Square and rounded dot styles&lt;/li&gt;
&lt;li&gt;PNG, SVG, EPS, PDF export&lt;/li&gt;
&lt;li&gt;No account required for basic use&lt;/li&gt;
&lt;li&gt;Server-side processing&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Best for:&lt;/strong&gt; One-off branded QR codes with a logo embedded. The design options are the most comprehensive of any free tool.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Limitation:&lt;/strong&gt; No bulk generation. Watermark on some download formats in the free tier. Uploads your data to their server.&lt;/p&gt;




&lt;h2&gt;
  
  
  3. QR Tiger — Best for dynamic QR codes
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;What it offers:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Static and dynamic QR codes (dynamic = changeable destination after printing)&lt;/li&gt;
&lt;li&gt;Logo embedding, custom colors&lt;/li&gt;
&lt;li&gt;Scan analytics (paid)&lt;/li&gt;
&lt;li&gt;Bulk generation (paid)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Best for:&lt;/strong&gt; Campaigns that need to change destination URLs after printing.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Limitation:&lt;/strong&gt; Dynamic QR codes are limited to 3 on the free plan. Watermark on free downloads. Signup required for most features.&lt;/p&gt;




&lt;h2&gt;
  
  
  4. Beaconstac — Best enterprise option
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;What it offers:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Dynamic QR codes with analytics&lt;/li&gt;
&lt;li&gt;Branded short URLs&lt;/li&gt;
&lt;li&gt;Team features, API access&lt;/li&gt;
&lt;li&gt;Campaign management&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Best for:&lt;/strong&gt; Teams managing multiple QR campaigns with analytics needs.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Limitation:&lt;/strong&gt; Primarily a paid product. Free tier is very limited. Not suited for casual or one-off use.&lt;/p&gt;




&lt;h2&gt;
  
  
  5. Google Charts API (deprecated but functional)
&lt;/h2&gt;

&lt;p&gt;The Google Charts QR code endpoint still works: &lt;code&gt;https://chart.googleapis.com/chart?chs=300x300&amp;amp;cht=qr&amp;amp;chl=YOUR_URL&lt;/code&gt;. Returns a QR code image directly.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Best for:&lt;/strong&gt; Developers embedding QR codes in web apps without installing a library.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Limitation:&lt;/strong&gt; Deprecated — no official support. No customization. Plain black and white only.&lt;/p&gt;




&lt;h2&gt;
  
  
  Comparison table
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Feature&lt;/th&gt;
&lt;th&gt;Ultimate Tools&lt;/th&gt;
&lt;th&gt;QR Code Monkey&lt;/th&gt;
&lt;th&gt;QR Tiger&lt;/th&gt;
&lt;th&gt;Beaconstac&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Free tier&lt;/td&gt;
&lt;td&gt;✅ Full&lt;/td&gt;
&lt;td&gt;✅ Most features&lt;/td&gt;
&lt;td&gt;Limited&lt;/td&gt;
&lt;td&gt;Very limited&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Bulk generation&lt;/td&gt;
&lt;td&gt;✅ (500 free)&lt;/td&gt;
&lt;td&gt;❌&lt;/td&gt;
&lt;td&gt;Paid&lt;/td&gt;
&lt;td&gt;Paid&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Dynamic QR codes&lt;/td&gt;
&lt;td&gt;❌&lt;/td&gt;
&lt;td&gt;❌&lt;/td&gt;
&lt;td&gt;Limited (3)&lt;/td&gt;
&lt;td&gt;Paid&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Custom colors&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Logo embedding&lt;/td&gt;
&lt;td&gt;❌&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Watermark-free&lt;/td&gt;
&lt;td&gt;✅ Always&lt;/td&gt;
&lt;td&gt;Partial&lt;/td&gt;
&lt;td&gt;❌ (free)&lt;/td&gt;
&lt;td&gt;❌ (free)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Account required&lt;/td&gt;
&lt;td&gt;❌ Never&lt;/td&gt;
&lt;td&gt;Optional&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;SVG export&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;Paid&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Browser-only (no upload)&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;❌&lt;/td&gt;
&lt;td&gt;❌&lt;/td&gt;
&lt;td&gt;❌&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Scan analytics&lt;/td&gt;
&lt;td&gt;❌&lt;/td&gt;
&lt;td&gt;❌&lt;/td&gt;
&lt;td&gt;Paid&lt;/td&gt;
&lt;td&gt;Paid&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;




&lt;h2&gt;
  
  
  Which should you use?
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;For bulk QR codes from a CSV:&lt;/strong&gt; &lt;a href="https://ultimatetools.io/tools/misc-tools/bulk-qr-code-generator/" rel="noopener noreferrer"&gt;Ultimate Tools Bulk QR Generator&lt;/a&gt; — free, up to 500, ZIP download, no watermark.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;For a single branded QR with a logo:&lt;/strong&gt; QR Code Monkey — the design options are unmatched for free tools.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;For dynamic QR codes that can be changed after printing:&lt;/strong&gt; QR Tiger (3 dynamic codes free) or Beaconstac (paid).&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;For privacy-sensitive content (WiFi passwords, internal URLs):&lt;/strong&gt; Ultimate Tools — the data is encoded in your browser and never sent to a server.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;For developer embedding:&lt;/strong&gt; Google Charts API endpoint or a JavaScript QR library (qrcode.js, qrious) bundled directly.&lt;/p&gt;




&lt;p&gt;Generate single or bulk QR codes at &lt;a href="https://ultimatetools.io/tools/misc-tools/bulk-qr-code-generator/" rel="noopener noreferrer"&gt;ultimatetools.io/tools/misc-tools/bulk-qr-code-generator/&lt;/a&gt; — free, no watermark, no account.&lt;/p&gt;

</description>
      <category>tools</category>
      <category>productivity</category>
      <category>webdev</category>
      <category>javascript</category>
    </item>
    <item>
      <title>Free Canva Alternatives for Image Editing — No Subscription, No Account</title>
      <dc:creator>Shaishav Patel</dc:creator>
      <pubDate>Mon, 11 May 2026 10:48:29 +0000</pubDate>
      <link>https://forem.com/shaishav_patel_271fdcd61a/free-canva-alternatives-for-image-editing-no-subscription-no-account-dpl</link>
      <guid>https://forem.com/shaishav_patel_271fdcd61a/free-canva-alternatives-for-image-editing-no-subscription-no-account-dpl</guid>
      <description>&lt;p&gt;Canva is a popular design tool. It has templates, drag-and-drop editing, brand kits, and a large asset library. It also requires an account, has a free-tier limit on exports and premium assets, and positions itself primarily as a design platform — not an image editing utility.&lt;/p&gt;

&lt;p&gt;If what you actually need is to resize, compress, crop, watermark, or convert an image, Canva is overkill — and you're usually waiting on it to load a full design environment for a 10-second task.&lt;/p&gt;

&lt;p&gt;These free browser-based alternatives from &lt;a href="https://ultimatetools.io/" rel="noopener noreferrer"&gt;Ultimate Tools&lt;/a&gt; cover the most common image editing tasks without any account, subscription, or file upload to a server.&lt;/p&gt;




&lt;h2&gt;
  
  
  Image Compression — Reduce file size without visible quality loss
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;What Canva does:&lt;/strong&gt; Canva exports at a fixed quality setting. You don't control compression level, and it exports to their format first, then converts. For large files, there's no way to preview compression before downloading.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Free alternative:&lt;/strong&gt; &lt;a href="https://ultimatetools.io/tools/image-tools/compress-image/" rel="noopener noreferrer"&gt;Image Compressor&lt;/a&gt; — drag in a JPEG or PNG, adjust quality slider, see the before/after file size instantly, download. Processing happens in the browser using the Canvas API — the image never leaves your device.&lt;/p&gt;




&lt;h2&gt;
  
  
  Image Resizing — Exact pixel dimensions
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;What Canva does:&lt;/strong&gt; Canva resizes within its canvas model — you resize the canvas and the content, not the raw image file. Getting an exact output pixel size requires knowing the canvas size, which doesn't always map cleanly to the final download size.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Free alternative:&lt;/strong&gt; &lt;a href="https://ultimatetools.io/tools/image-tools/resize-image/" rel="noopener noreferrer"&gt;Image Resizer&lt;/a&gt; — enter exact width and height in pixels (or a percentage), toggle aspect ratio lock, download. What you set is what you get.&lt;/p&gt;




&lt;h2&gt;
  
  
  Image Cropping — Freehand or aspect ratio locked
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;What Canva does:&lt;/strong&gt; Canva cropping works within the design canvas. Good for design projects; excessive for simply cropping a photo to a specific dimension.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Free alternative:&lt;/strong&gt; &lt;a href="https://ultimatetools.io/tools/image-tools/crop-image/" rel="noopener noreferrer"&gt;Crop Image&lt;/a&gt; — freehand crop or lock to preset ratios (1:1, 16:9, 4:3, etc.), drag handles, download the cropped portion at full original resolution.&lt;/p&gt;




&lt;h2&gt;
  
  
  Watermarking — Add text or logo overlay
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;What Canva does:&lt;/strong&gt; Canva can add text overlays as a design layer. This requires working in the Canva canvas, uploading the image as a background, adding text, and exporting. It works, but it's slow for a single image.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Free alternative:&lt;/strong&gt; &lt;a href="https://ultimatetools.io/tools/image-tools/watermark-image/" rel="noopener noreferrer"&gt;Watermark Image&lt;/a&gt; — upload an image, type your watermark text, adjust font size, opacity, position, and color, download. Single step. No design canvas to manage.&lt;/p&gt;




&lt;h2&gt;
  
  
  Image Format Conversion — JPG, PNG, WebP
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;What Canva does:&lt;/strong&gt; Canva exports in JPG, PNG, PDF, SVG, or MP4. Format conversion is tied to the export flow, not a standalone utility.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Free alternative:&lt;/strong&gt; &lt;a href="https://ultimatetools.io/tools/image-tools/convert-image/" rel="noopener noreferrer"&gt;Image Converter&lt;/a&gt; — convert between JPEG, PNG, WebP, and other formats directly. No design canvas involved.&lt;/p&gt;




&lt;h2&gt;
  
  
  Background Removal — Where Canva wins
&lt;/h2&gt;

&lt;p&gt;Canva's AI background removal (Magic Eraser, BG Remover) is genuinely useful and works well on most photos. Ultimate Tools doesn't currently offer background removal. If removing backgrounds is your primary need, Canva's free tier or Remove.bg is the better pick for that specific task.&lt;/p&gt;




&lt;h2&gt;
  
  
  Summary: which to use
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Task&lt;/th&gt;
&lt;th&gt;Canva (free)&lt;/th&gt;
&lt;th&gt;Ultimate Tools&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Compress image&lt;/td&gt;
&lt;td&gt;Limited&lt;/td&gt;
&lt;td&gt;✅ Free, browser-based&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Resize to exact pixels&lt;/td&gt;
&lt;td&gt;Indirect&lt;/td&gt;
&lt;td&gt;✅ Direct pixel input&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Crop with aspect ratio&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Watermark text&lt;/td&gt;
&lt;td&gt;✅ (via canvas)&lt;/td&gt;
&lt;td&gt;✅ (direct)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Format conversion&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Background removal&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;❌&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Account required&lt;/td&gt;
&lt;td&gt;✅ Required&lt;/td&gt;
&lt;td&gt;❌ Never&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;File upload to server&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;❌ Never&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Ads / premium prompts&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;❌&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;Use Canva if:&lt;/strong&gt; You need a full design environment, templates, brand assets, or background removal.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Use Ultimate Tools if:&lt;/strong&gt; You need to resize, compress, crop, watermark, or convert an image quickly — without creating an account or uploading your file to a server.&lt;/p&gt;

&lt;p&gt;The full image toolkit is at &lt;a href="https://ultimatetools.io/tools/image-tools/" rel="noopener noreferrer"&gt;ultimatetools.io/tools/image-tools/&lt;/a&gt; — all browser-based, all free, no signup required.&lt;/p&gt;

</description>
      <category>tools</category>
      <category>productivity</category>
      <category>webdev</category>
      <category>javascript</category>
    </item>
    <item>
      <title>How to Resize an Image for Free — Without Photoshop or Subscriptions</title>
      <dc:creator>Shaishav Patel</dc:creator>
      <pubDate>Mon, 11 May 2026 10:43:11 +0000</pubDate>
      <link>https://forem.com/shaishav_patel_271fdcd61a/how-to-resize-an-image-for-free-without-photoshop-or-subscriptions-82j</link>
      <guid>https://forem.com/shaishav_patel_271fdcd61a/how-to-resize-an-image-for-free-without-photoshop-or-subscriptions-82j</guid>
      <description>&lt;p&gt;Resizing an image sounds like it should take 10 seconds. But the default paths — "use Photoshop" or "use the Windows photo editor" — either require software you don't have or produce poor quality at unusual dimensions. And most "free" online tools have file size limits, require sign-ins, or watermark the output.&lt;/p&gt;

&lt;p&gt;Here's how to resize images free, quickly, and without any of that friction.&lt;/p&gt;




&lt;h2&gt;
  
  
  Option 1: Browser-based image resizer (no upload)
&lt;/h2&gt;

&lt;p&gt;The &lt;a href="https://ultimatetools.io/tools/image-tools/resize-image/" rel="noopener noreferrer"&gt;Image Resizer&lt;/a&gt; at Ultimate Tools processes your image entirely in the browser. The file never leaves your device.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;How it works:&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Open the tool&lt;/li&gt;
&lt;li&gt;Drop your image (JPEG, PNG, WebP, or GIF)&lt;/li&gt;
&lt;li&gt;Set the target dimensions — by pixels or by percentage&lt;/li&gt;
&lt;li&gt;Toggle aspect ratio lock to maintain proportions (optional)&lt;/li&gt;
&lt;li&gt;Click Resize&lt;/li&gt;
&lt;li&gt;Download the resized image&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;You can set both width and height independently, or lock the aspect ratio so changing one dimension automatically adjusts the other.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;When to use this:&lt;/strong&gt; Any time you need a specific pixel size — social media dimensions, profile photos, banner ads, or assets for a website. The image never leaves your device.&lt;/p&gt;




&lt;h2&gt;
  
  
  Common dimensions by platform
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Platform&lt;/th&gt;
&lt;th&gt;Recommended dimensions&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Twitter/X profile photo&lt;/td&gt;
&lt;td&gt;400×400px&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Twitter/X header&lt;/td&gt;
&lt;td&gt;1500×500px&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;LinkedIn profile photo&lt;/td&gt;
&lt;td&gt;400×400px&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;LinkedIn banner&lt;/td&gt;
&lt;td&gt;1584×396px&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Facebook cover photo&lt;/td&gt;
&lt;td&gt;820×312px&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Instagram post (square)&lt;/td&gt;
&lt;td&gt;1080×1080px&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;YouTube thumbnail&lt;/td&gt;
&lt;td&gt;1280×720px&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Website favicon&lt;/td&gt;
&lt;td&gt;32×32px, 64×64px&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Open Graph image&lt;/td&gt;
&lt;td&gt;1200×630px&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;




&lt;h2&gt;
  
  
  Option 2: Windows Photos (built-in)
&lt;/h2&gt;

&lt;p&gt;On Windows 10/11, Windows Photos can resize images:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Open the image in Photos&lt;/li&gt;
&lt;li&gt;Click the three-dot menu (···) → Resize&lt;/li&gt;
&lt;li&gt;Choose a preset or enter custom dimensions&lt;/li&gt;
&lt;li&gt;Save&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The quality on Windows Photos is acceptable for basic resizing. It doesn't give you precise pixel control over the output dimensions.&lt;/p&gt;




&lt;h2&gt;
  
  
  Option 3: macOS Preview (built-in)
&lt;/h2&gt;

&lt;p&gt;On a Mac:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Open the image in Preview&lt;/li&gt;
&lt;li&gt;Tools → Adjust Size&lt;/li&gt;
&lt;li&gt;Enter width or height (and check "Scale proportionally" to lock aspect ratio)&lt;/li&gt;
&lt;li&gt;File → Export to save&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Preview gives more precise control than Windows Photos. You can set exact pixel dimensions and choose resampling quality.&lt;/p&gt;




&lt;h2&gt;
  
  
  Option 4: Command line (ImageMagick)
&lt;/h2&gt;

&lt;p&gt;For developers who need to resize many images at once:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Resize to exactly 800×600&lt;/span&gt;
magick input.jpg &lt;span class="nt"&gt;-resize&lt;/span&gt; 800x600! output.jpg

&lt;span class="c"&gt;# Resize to 800px wide, maintain aspect ratio&lt;/span&gt;
magick input.jpg &lt;span class="nt"&gt;-resize&lt;/span&gt; 800 output.jpg

&lt;span class="c"&gt;# Resize to max 1920×1080, maintain aspect ratio&lt;/span&gt;
magick input.jpg &lt;span class="nt"&gt;-resize&lt;/span&gt; 1920x1080 output.jpg

&lt;span class="c"&gt;# Batch resize all JPEGs in a folder&lt;/span&gt;
magick mogrify &lt;span class="nt"&gt;-resize&lt;/span&gt; 1200x630 &lt;span class="k"&gt;*&lt;/span&gt;.jpg
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;ImageMagick is free, open source, and handles batch operations. The &lt;code&gt;!&lt;/code&gt; flag forces exact dimensions, ignoring aspect ratio.&lt;/p&gt;




&lt;h2&gt;
  
  
  What happens to quality when resizing?
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Scaling down (downsizing)&lt;/strong&gt; — Image quality is generally preserved. Information is discarded but what remains is accurate. A 4000×3000 photo resized to 800×600 looks sharp.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Scaling up (upsizing/upscaling)&lt;/strong&gt; — The tool has to invent new pixels. This always introduces some blurring. Traditional resizing (bilinear, bicubic) handles modest upscaling (up to 2×) reasonably well. For larger upscaling, AI-based tools (Topaz Gigapixel, Adobe Super Resolution) produce better results.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;File format matters&lt;/strong&gt; — Resizing a JPEG and saving as JPEG applies JPEG compression on top of the resize. Each save cycle can slightly degrade quality. Save as PNG for lossless output if you're going to edit further; convert to JPEG only for the final export.&lt;/p&gt;




&lt;h2&gt;
  
  
  Quick comparison
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Method&lt;/th&gt;
&lt;th&gt;Cost&lt;/th&gt;
&lt;th&gt;Upload required&lt;/th&gt;
&lt;th&gt;Platform&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Ultimate Tools (browser)&lt;/td&gt;
&lt;td&gt;Free&lt;/td&gt;
&lt;td&gt;❌ Never&lt;/td&gt;
&lt;td&gt;Any browser&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Windows Photos&lt;/td&gt;
&lt;td&gt;Free&lt;/td&gt;
&lt;td&gt;❌ Local&lt;/td&gt;
&lt;td&gt;Windows&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;macOS Preview&lt;/td&gt;
&lt;td&gt;Free&lt;/td&gt;
&lt;td&gt;❌ Local&lt;/td&gt;
&lt;td&gt;Mac&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;ImageMagick&lt;/td&gt;
&lt;td&gt;Free&lt;/td&gt;
&lt;td&gt;❌ Local&lt;/td&gt;
&lt;td&gt;Any OS&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Most online tools&lt;/td&gt;
&lt;td&gt;Free/paid&lt;/td&gt;
&lt;td&gt;✅ Yes&lt;/td&gt;
&lt;td&gt;Any browser&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;The &lt;a href="https://ultimatetools.io/tools/image-tools/resize-image/" rel="noopener noreferrer"&gt;Image Resizer&lt;/a&gt; is the fastest option for one-off resizes in any browser — set dimensions, download, done. No upload, no account.&lt;/p&gt;

</description>
      <category>tools</category>
      <category>productivity</category>
      <category>webdev</category>
      <category>javascript</category>
    </item>
    <item>
      <title>The Complete Guide to QR Codes — How They Work, When to Use Them, and How to Generate Them Free</title>
      <dc:creator>Shaishav Patel</dc:creator>
      <pubDate>Mon, 11 May 2026 10:43:05 +0000</pubDate>
      <link>https://forem.com/shaishav_patel_271fdcd61a/the-complete-guide-to-qr-codes-how-they-work-when-to-use-them-and-how-to-generate-them-free-4b58</link>
      <guid>https://forem.com/shaishav_patel_271fdcd61a/the-complete-guide-to-qr-codes-how-they-work-when-to-use-them-and-how-to-generate-them-free-4b58</guid>
      <description>&lt;p&gt;QR codes are everywhere — on packaging, menus, business cards, billboards, and event tickets. Most people know how to scan one. Fewer people know how to generate exactly the kind they need, or what the different formats are for.&lt;/p&gt;

&lt;p&gt;This post covers how QR codes work, the different data types they support, customization options, and how to generate them for free without any account.&lt;/p&gt;




&lt;h2&gt;
  
  
  How QR codes work
&lt;/h2&gt;

&lt;p&gt;A QR code (Quick Response code) is a two-dimensional barcode that encodes data as a pattern of black and white squares. The data can be a URL, plain text, contact details, WiFi credentials, or any string of characters.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Key structural elements:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Finder patterns&lt;/strong&gt; — the three large square markers in the corners. Let scanners locate and orient the code.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Data area&lt;/strong&gt; — the matrix of small squares that encodes the actual content.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Error correction&lt;/strong&gt; — QR codes can be partially damaged or obscured and still scan correctly. Four levels: L (7% recovery), M (15%), Q (25%), H (30%).&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Higher error correction = more redundant data = larger QR code for the same payload.&lt;/p&gt;




&lt;h2&gt;
  
  
  QR code data types
&lt;/h2&gt;

&lt;h3&gt;
  
  
  URL
&lt;/h3&gt;

&lt;p&gt;The most common type. Encodes a full URL. When scanned, the device opens the URL in the default browser.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;https://ultimatetools.io/tools/misc-tools/qr-code-generator/
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Plain text
&lt;/h3&gt;

&lt;p&gt;Encodes a string of text. Scanners display the text directly without opening a browser.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Table 4 — WiFi password is: coffee2024
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  WiFi credentials
&lt;/h3&gt;

&lt;p&gt;Encodes WiFi network information using the &lt;code&gt;WIFI:&lt;/code&gt; protocol. When scanned on iOS or Android, the device offers to join the network automatically.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;WIFI:T:WPA;S:NetworkName;P:password123;;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Parameters:&lt;/strong&gt; &lt;code&gt;T&lt;/code&gt; = security type (WPA/WEP/nopass), &lt;code&gt;S&lt;/code&gt; = SSID, &lt;code&gt;P&lt;/code&gt; = password, &lt;code&gt;H&lt;/code&gt; = hidden network.&lt;/p&gt;

&lt;h3&gt;
  
  
  Contact (vCard)
&lt;/h3&gt;

&lt;p&gt;Encodes a vCard string so scanning adds the contact directly to the device's address book.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;BEGIN:VCARD
VERSION:3.0
FN:Jane Smith
ORG:Acme Corp
TEL:+1-555-0100
EMAIL:jane@acme.com
END:VCARD
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Email
&lt;/h3&gt;

&lt;p&gt;Opens the email client with a pre-filled recipient and optional subject/body.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;mailto:contact@example.com?subject=Hello&amp;amp;body=I%20saw%20your%20QR%20code
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Phone / SMS
&lt;/h3&gt;

&lt;p&gt;Initiates a call or opens the SMS app.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;tel:+15550100
sms:+15550100?body=Hi
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  Static vs dynamic QR codes
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Static QR codes&lt;/strong&gt; — the destination URL or data is encoded permanently in the QR code pattern. Once printed, it can't be changed. Free to generate; standard for most uses.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Dynamic QR codes&lt;/strong&gt; — a short URL redirect is encoded instead of the actual destination. The redirect can be updated after printing. Requires a service with a redirect infrastructure. Typically paid (QR Tiger, Bitly QR codes, etc.).&lt;/p&gt;

&lt;p&gt;For most use cases, static QR codes are sufficient. You only need dynamic codes if you've already printed materials and need to change the destination — for example, a flyer with a QR code pointing to a campaign page that later moves.&lt;/p&gt;




&lt;h2&gt;
  
  
  Customization options
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Colors
&lt;/h3&gt;

&lt;p&gt;QR codes don't have to be black on white. Any high-contrast color combination works. Minimum recommended contrast ratio for reliable scanning: 4:1. Avoid light foreground on white background.&lt;/p&gt;

&lt;h3&gt;
  
  
  Dot style
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Square&lt;/strong&gt; — classic, maximum scanner compatibility&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Rounded&lt;/strong&gt; — softer appearance, still highly scannable&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Dots&lt;/strong&gt; — circular modules, modern look&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Size
&lt;/h3&gt;

&lt;p&gt;For print: minimum 1cm × 1cm. For billboards or signage: scale up proportionally — the scan distance is the limiting factor.&lt;/p&gt;

&lt;h3&gt;
  
  
  Format
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;PNG&lt;/strong&gt; — raster image, best for web and digital use&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;SVG&lt;/strong&gt; — vector, scales to any size without quality loss, best for print&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  How to generate a QR code for free
&lt;/h2&gt;

&lt;p&gt;The &lt;a href="https://ultimatetools.io/tools/misc-tools/qr-code-generator/" rel="noopener noreferrer"&gt;QR Code Generator&lt;/a&gt; generates single QR codes in the browser. Choose data type, enter the content, customize colors and dot style, download as PNG or SVG. No account, no watermark.&lt;/p&gt;

&lt;p&gt;For batch generation from a list of URLs or a CSV file, use the &lt;a href="https://ultimatetools.io/tools/misc-tools/bulk-qr-code-generator/" rel="noopener noreferrer"&gt;Bulk QR Code Generator&lt;/a&gt; — generates up to 500 QR codes at once and downloads them as a ZIP.&lt;/p&gt;

&lt;p&gt;Both tools run entirely in your browser. The content you encode never leaves your device.&lt;/p&gt;




&lt;h2&gt;
  
  
  How to scan a QR code
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;iOS&lt;/strong&gt; — Camera app (built-in since iOS 11). Point at the code, tap the notification.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Android&lt;/strong&gt; — Camera app (built-in on most devices since Android 9), or Google Lens.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Desktop&lt;/strong&gt; — Browser extensions (Chrome has a built-in "Use your phone" scan option), or use an &lt;a href="https://ultimatetools.io/tools/misc-tools/qr-code-scanner/" rel="noopener noreferrer"&gt;online QR scanner&lt;/a&gt; to scan from an image file.&lt;/p&gt;




&lt;h2&gt;
  
  
  Best practices
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Always test before printing.&lt;/strong&gt; Scan the QR code with at least two different devices before putting it on physical materials.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Add a call to action.&lt;/strong&gt; "Scan to see the menu" or "Scan to get the discount code." People hesitate to scan QR codes without context.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Keep URLs short.&lt;/strong&gt; Longer URLs = more data = denser QR code = harder to scan at small sizes. Use a short URL if the destination URL is very long.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Don't put QR codes where phones can't connect.&lt;/strong&gt; Underground venues, parking garages, and dead zones don't work well for URL QR codes.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;For print, use SVG.&lt;/strong&gt; SVG scales cleanly to any print size without pixelation.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;




&lt;p&gt;Generate yours at &lt;a href="https://ultimatetools.io/tools/misc-tools/qr-code-generator/" rel="noopener noreferrer"&gt;ultimatetools.io/tools/misc-tools/qr-code-generator/&lt;/a&gt; — single QR codes free, no account, no watermark. For bulk generation: &lt;a href="https://ultimatetools.io/tools/misc-tools/bulk-qr-code-generator/" rel="noopener noreferrer"&gt;ultimatetools.io/tools/misc-tools/bulk-qr-code-generator/&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>tools</category>
      <category>webdev</category>
      <category>productivity</category>
      <category>javascript</category>
    </item>
    <item>
      <title>6 Free Text Tools Content Writers Use Every Day</title>
      <dc:creator>Shaishav Patel</dc:creator>
      <pubDate>Mon, 11 May 2026 10:40:45 +0000</pubDate>
      <link>https://forem.com/shaishav_patel_271fdcd61a/6-free-text-tools-content-writers-use-every-day-28nm</link>
      <guid>https://forem.com/shaishav_patel_271fdcd61a/6-free-text-tools-content-writers-use-every-day-28nm</guid>
      <description>&lt;p&gt;Content writing involves a lot of repetitive small tasks: counting words, converting text cases for headlines, generating placeholder text, checking readability, and validating JSON for technical content. Most writers solve these with a mix of bookmarks, browser extensions, and standalone apps.&lt;/p&gt;

&lt;p&gt;These free text tools from &lt;a href="https://ultimatetools.io/" rel="noopener noreferrer"&gt;Ultimate Tools&lt;/a&gt; handle the most common writing tasks in the browser — no extension, no login, and no file upload.&lt;/p&gt;




&lt;h2&gt;
  
  
  1. Word Counter — The one you'll use every day
&lt;/h2&gt;

&lt;p&gt;The &lt;a href="https://ultimatetools.io/tools/misc-tools/word-counter/" rel="noopener noreferrer"&gt;Word Counter&lt;/a&gt; tracks words, characters (with and without spaces), sentences, paragraphs, and estimated reading time as you type. It updates in real time.&lt;/p&gt;

&lt;p&gt;Most word processors have a word count. The advantage of a dedicated tool is speed: paste from anywhere, see the count instantly without opening a document editor.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Use cases:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Verifying a blog post hits the target word count before publishing&lt;/li&gt;
&lt;li&gt;Checking that a meta description is under 160 characters&lt;/li&gt;
&lt;li&gt;Estimating reading time for an article or email&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  2. Case Converter — Format headlines and titles correctly
&lt;/h2&gt;

&lt;p&gt;The &lt;a href="https://ultimatetools.io/tools/misc-tools/case-converter/" rel="noopener noreferrer"&gt;Case Converter&lt;/a&gt; converts text between: Title Case, UPPER CASE, lower case, Sentence case, camelCase, snake_case, and kebab-case.&lt;/p&gt;

&lt;p&gt;Title Case conversion is the most useful for writers: paste a headline, click "Title Case," copy. The tool applies standard capitalization rules (don't capitalize prepositions, articles, and conjunctions under 5 letters unless they're first or last).&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Use cases:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Converting all-caps subject lines to Title Case for email campaigns&lt;/li&gt;
&lt;li&gt;Converting blog post titles that were drafted in lowercase&lt;/li&gt;
&lt;li&gt;Converting snake_case variable names to human-readable labels&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  3. Lorem Ipsum Generator — Placeholder text for mockups and layouts
&lt;/h2&gt;

&lt;p&gt;The &lt;a href="https://ultimatetools.io/tools/misc-tools/lorem-ipsum/" rel="noopener noreferrer"&gt;Lorem Ipsum Generator&lt;/a&gt; generates placeholder text by words, sentences, or paragraphs. Useful when building content templates, email layouts, or showing a client what a page will look like with real content.&lt;/p&gt;

&lt;p&gt;Unlike copying from lorem ipsum websites, the generator lets you specify exactly how many words or paragraphs you need.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Use cases:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Filling a Figma or Canva template with realistic-length placeholder text&lt;/li&gt;
&lt;li&gt;Testing how a CMS layout handles different text lengths&lt;/li&gt;
&lt;li&gt;Generating filler content for a prototype or wireframe&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  4. Text Repeater — Repeat strings and patterns
&lt;/h2&gt;

&lt;p&gt;When testing how a UI handles long or repeated content, the &lt;a href="https://ultimatetools.io/tools/misc-tools/text-repeater/" rel="noopener noreferrer"&gt;Text Repeater&lt;/a&gt; repeats any string N times with a configurable separator.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Use cases:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Testing how a character limit handles repeated input&lt;/li&gt;
&lt;li&gt;Generating repeated rows for table mockups&lt;/li&gt;
&lt;li&gt;Creating repetitive test content for CMS uploads&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  5. Number to Words — Convert figures for formal writing
&lt;/h2&gt;

&lt;p&gt;Formal writing (legal documents, checks, contracts) requires numbers to be written out in words. The &lt;a href="https://ultimatetools.io/tools/misc-tools/number-to-words/" rel="noopener noreferrer"&gt;Number to Words converter&lt;/a&gt; converts any number to its word form — "1,234,567" → "one million two hundred thirty-four thousand five hundred sixty-seven."&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Use cases:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Writing invoice amounts in words for formal contracts&lt;/li&gt;
&lt;li&gt;Converting financial figures for press releases or annual reports&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  6. JSON Formatter — Readable JSON for technical content
&lt;/h2&gt;

&lt;p&gt;Technical writers and developer advocates often paste JSON into documentation. Unformatted JSON is unreadable. The &lt;a href="https://ultimatetools.io/tools/misc-tools/json-formatter/" rel="noopener noreferrer"&gt;JSON Formatter&lt;/a&gt; pretty-prints JSON with proper indentation and highlights syntax errors.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Use cases:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Formatting API response examples for documentation&lt;/li&gt;
&lt;li&gt;Validating JSON before embedding it in a tutorial&lt;/li&gt;
&lt;li&gt;Minifying JSON for code examples where space matters&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  The common thread
&lt;/h2&gt;

&lt;p&gt;All of these tools work on text you paste into a browser window — no file upload, no account. They're fast because there's no round-trip to a server: processing happens locally in the JavaScript engine.&lt;/p&gt;

&lt;p&gt;The full text tools collection is at &lt;a href="https://ultimatetools.io/" rel="noopener noreferrer"&gt;ultimatetools.io&lt;/a&gt; — word counter, case converter, lorem ipsum, and more. Free, instant, no signup.&lt;/p&gt;

</description>
      <category>tools</category>
      <category>productivity</category>
      <category>webdev</category>
      <category>beginners</category>
    </item>
    <item>
      <title>How to Compress a PDF Without Losing Quality — 4 Free Methods</title>
      <dc:creator>Shaishav Patel</dc:creator>
      <pubDate>Mon, 11 May 2026 10:39:08 +0000</pubDate>
      <link>https://forem.com/shaishav_patel_271fdcd61a/how-to-compress-a-pdf-without-losing-quality-4-free-methods-no6</link>
      <guid>https://forem.com/shaishav_patel_271fdcd61a/how-to-compress-a-pdf-without-losing-quality-4-free-methods-no6</guid>
      <description>&lt;p&gt;PDF files get large fast — especially scanned documents, PDFs with embedded images, or multi-page reports exported from design tools. Email attachment limits, upload portals with size caps, and slow file transfers all become problems.&lt;/p&gt;

&lt;p&gt;Here are four free methods to compress a PDF, what each one actually does, and when to use which.&lt;/p&gt;




&lt;h2&gt;
  
  
  Method 1: Browser-based compression (no upload)
&lt;/h2&gt;

&lt;p&gt;The &lt;a href="https://ultimatetools.io/tools/pdf-tools/compress-pdf/" rel="noopener noreferrer"&gt;PDF Compressor&lt;/a&gt; at Ultimate Tools compresses your PDF entirely in your browser. The file never leaves your device.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;How it works:&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Open the tool&lt;/li&gt;
&lt;li&gt;Drop your PDF file&lt;/li&gt;
&lt;li&gt;Choose compression level (light, medium, strong)&lt;/li&gt;
&lt;li&gt;Click Compress&lt;/li&gt;
&lt;li&gt;Download the compressed file&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The browser-side processing uses pdf-lib to re-encode the document. Image-heavy PDFs see the largest reductions (50–80% file size reduction is common). Text-only PDFs see smaller reductions since text data compresses well even in the original.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;When to use this:&lt;/strong&gt; Any PDF with sensitive content (contracts, financial documents, medical records). The file never touches a server.&lt;/p&gt;




&lt;h2&gt;
  
  
  Method 2: Adobe Acrobat (free web version)
&lt;/h2&gt;

&lt;p&gt;Adobe offers a free PDF compressor at the Adobe Acrobat web tool. It requires signing in with an Adobe ID (or Google/Apple account), but the compression itself is free for occasional use.&lt;/p&gt;

&lt;p&gt;The Adobe tool uses server-side processing — your file is uploaded, compressed, and downloaded back. Quality tends to be good because Adobe's compression engine is mature.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;When to use this:&lt;/strong&gt; When you don't have privacy concerns and want a well-known brand's compression engine.&lt;/p&gt;




&lt;h2&gt;
  
  
  Method 3: macOS Preview (built-in, free)
&lt;/h2&gt;

&lt;p&gt;On a Mac, you can reduce PDF file size using Preview's "Quartz Filter":&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Open the PDF in Preview&lt;/li&gt;
&lt;li&gt;File → Export&lt;/li&gt;
&lt;li&gt;Quartz Filter → Reduce File Size&lt;/li&gt;
&lt;li&gt;Export&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The Reduce File Size filter aggressively compresses images, sometimes too aggressively. The result can look pixelated for image-heavy PDFs. Best for text-heavy documents where image quality is less critical.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;When to use this:&lt;/strong&gt; Quick compression on a Mac without any additional tools. Acceptable for internal documents where exact image quality doesn't matter.&lt;/p&gt;




&lt;h2&gt;
  
  
  Method 4: Ghostscript (command line, free)
&lt;/h2&gt;

&lt;p&gt;For developers or power users who want maximum control:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;gs &lt;span class="nt"&gt;-sDEVICE&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;pdfwrite &lt;span class="nt"&gt;-dCompatibilityLevel&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;1.4 &lt;span class="se"&gt;\&lt;/span&gt;
   &lt;span class="nt"&gt;-dPDFSETTINGS&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;/screen &lt;span class="se"&gt;\&lt;/span&gt;
   &lt;span class="nt"&gt;-dNOPAUSE&lt;/span&gt; &lt;span class="nt"&gt;-dQUIET&lt;/span&gt; &lt;span class="nt"&gt;-dBATCH&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
   &lt;span class="nt"&gt;-sOutputFile&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;compressed.pdf input.pdf
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;-dPDFSETTINGS&lt;/code&gt; controls quality:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;/screen&lt;/code&gt; — lowest quality, smallest size (72 DPI images)&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;/ebook&lt;/code&gt; — medium quality (150 DPI images)&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;/printer&lt;/code&gt; — high quality (300 DPI images)&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;/prepress&lt;/code&gt; — highest quality (300+ DPI, color profiles preserved)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Ghostscript is the most powerful option — it rebuilds the PDF from scratch and can achieve much higher compression ratios than web tools.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;When to use this:&lt;/strong&gt; Batch processing multiple PDFs, scripted automation, or when you need fine-grained control over output quality.&lt;/p&gt;




&lt;h2&gt;
  
  
  Why some PDFs compress more than others
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Image-heavy PDFs&lt;/strong&gt; — Large JPEG or PNG images embedded in a PDF compress dramatically. A scanned document that's 20MB often compresses to 4–5MB.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Text-only PDFs&lt;/strong&gt; — Text in PDFs is stored as vector data or fonts, which already compresses well. A 2MB text PDF might only reduce to 1.7MB.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Already-compressed PDFs&lt;/strong&gt; — PDFs that were previously exported at screen resolution or already optimized won't compress further. You may see 0% or even slight size increase from recompression.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Encrypted PDFs&lt;/strong&gt; — Password-protected PDFs can't be recompressed without first removing the password.&lt;/p&gt;




&lt;h2&gt;
  
  
  Quick comparison
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Method&lt;/th&gt;
&lt;th&gt;Cost&lt;/th&gt;
&lt;th&gt;Upload required&lt;/th&gt;
&lt;th&gt;Platform&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Ultimate Tools (browser)&lt;/td&gt;
&lt;td&gt;Free&lt;/td&gt;
&lt;td&gt;❌ Never&lt;/td&gt;
&lt;td&gt;Any browser&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Adobe Acrobat web&lt;/td&gt;
&lt;td&gt;Free (login req.)&lt;/td&gt;
&lt;td&gt;✅ Yes&lt;/td&gt;
&lt;td&gt;Any browser&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;macOS Preview&lt;/td&gt;
&lt;td&gt;Free&lt;/td&gt;
&lt;td&gt;❌ Local&lt;/td&gt;
&lt;td&gt;Mac only&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Ghostscript&lt;/td&gt;
&lt;td&gt;Free&lt;/td&gt;
&lt;td&gt;❌ Local&lt;/td&gt;
&lt;td&gt;Any OS&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;For a free, no-upload option that works in any browser, the &lt;a href="https://ultimatetools.io/tools/pdf-tools/compress-pdf/" rel="noopener noreferrer"&gt;PDF Compressor&lt;/a&gt; is the quickest path — drop the file, download, done.&lt;/p&gt;

</description>
      <category>tools</category>
      <category>productivity</category>
      <category>webdev</category>
      <category>javascript</category>
    </item>
  </channel>
</rss>
