Last updated: February 23, 2025

<span aria-hidden="true" id="optimize-pngs-in-the-browser-with-optipngjs"></span>

# Optimize PNGs in the browser with Optipng.js

![Tim Koschützki](/assets/images/teammates/avatar-tim-kos-1.jpg?dpl=dpl_C6YH6XrtnwbHLJcm1LDKywQn4CB3)

#### Tim Koschützki

Co-founder · Berlin, Germany · Show bio

[](https://x.com/tim%5Fkos)[](https://github.com/tim-kos)

Optimizing PNG images in the browser can significantly improve web performance by reducing file sizes without quality loss. OptiPNG.js, a JavaScript port of the popular OptiPNG tool, enables developers to implement efficient client-side PNG optimization. This guide explores how to integrate and use OptiPNG.js in web applications.

<span aria-hidden="true" id="understanding-optipngjs"></span>

## Understanding Optipng.js

OptiPNG.js brings the powerful lossless PNG compression capabilities of OptiPNG to the browser environment. It works by recompressing PNG images using optimization algorithms that reduce file size while maintaining perfect pixel-for-pixel image quality.

<span aria-hidden="true" id="implementation"></span>

## Implementation

First, include the OptiPNG.js library in your project:

```html
<script src="https://unpkg.com/@jsquash/opng-wasm@1.0.0/dist/opng.js"></script>

```

Create a basic interface for file selection and optimization:

```html
<input type="file" id="pngInput" accept=".png" />
<button id="optimizeBtn" disabled>Optimize PNG</button>
<div id="stats"></div>

<script>
  const input = document.getElementById('pngInput')
  const button = document.getElementById('optimizeBtn')
  const stats = document.getElementById('stats')

  // Initialize OptiPNG.js
  let opngModule

  OptiPNG.init().then((module) => {
    opngModule = module
    button.disabled = false
  })

  async function optimizePNG(file) {
    if (file.size > 5 * 1024 * 1024) {
      throw new Error('File too large (max 5MB)')
    }

    const buffer = await file.arrayBuffer()
    const optimizedBuffer = await opngModule.optimize(new Uint8Array(buffer), {
      optimizationLevel: 2,
    })

    return new Blob([optimizedBuffer], { type: 'image/png' })
  }

  button.addEventListener('click', async () => {
    const file = input.files[0]
    if (!file) return

    try {
      button.disabled = true
      stats.textContent = 'Optimizing...'

      const startTime = performance.now()
      const optimizedBlob = await optimizePNG(file)
      const endTime = performance.now()

      const originalSize = (file.size / 1024).toFixed(2)
      const optimizedSize = (optimizedBlob.size / 1024).toFixed(2)
      const savings = (100 * (1 - optimizedBlob.size / file.size)).toFixed(1)
      const duration = (endTime - startTime).toFixed(0)

      stats.innerHTML = `
      Original size: ${originalSize}KB<br>
      Optimized size: ${optimizedSize}KB<br>
      Savings: ${savings}%<br>
      Processing time: ${duration}ms
    `

      // Create download link
      const url = URL.createObjectURL(optimizedBlob)
      const a = document.createElement('a')
      a.href = url
      a.download = file.name.replace('.png', '.optimized.png')
      a.textContent = 'Download optimized PNG'
      stats.appendChild(document.createElement('br'))
      stats.appendChild(a)
    } catch (error) {
      stats.textContent = `Error: ${error.message}`
    } finally {
      button.disabled = false
    }
  })
</script>

```

<span aria-hidden="true" id="using-web-workers-for-better-performance"></span>

## Using Web Workers for better performance

For handling larger images or multiple files, implement optimization in a Web Worker to prevent UI blocking:

```javascript
// optimizer.worker.js
importScripts('https://unpkg.com/@jsquash/opng-wasm@1.0.0/dist/opng.js')

let opngModule

OptiPNG.init().then((module) => {
  opngModule = module
})

self.onmessage = async ({ data }) => {
  try {
    const optimizedBuffer = await opngModule.optimize(new Uint8Array(data.buffer), {
      optimizationLevel: data.level || 2,
    })
    self.postMessage({ buffer: optimizedBuffer.buffer, error: null }, [optimizedBuffer.buffer])
  } catch (error) {
    self.postMessage({ buffer: null, error: error.message })
  }
}

```

<span aria-hidden="true" id="browser-compatibility"></span>

## Browser compatibility

OptiPNG.js works in all modern browsers that support WebAssembly, which includes:

* Chrome 57+
* Firefox 52+
* Safari 11+
* Edge 79+

Implement feature detection to ensure compatibility:

```javascript
if (!('WebAssembly' in window)) {
  console.error('WebAssembly is not supported in this browser')
  button.disabled = true
  stats.textContent = 'Browser not supported'
}

```

<span aria-hidden="true" id="performance-considerations"></span>

## Performance considerations

When implementing OptiPNG.js, keep in mind:

* Limit input file sizes to 5MB for optimal performance
* Use Web Workers for files larger than 1MB
* Consider the following optimization levels:
  * Level 1: Fast optimization (0.1-0.3s)
  * Level 2: Balanced optimization (0.3-0.7s)
  * Level 3: Maximum optimization (0.7-2.0s)

<span aria-hidden="true" id="use-cases"></span>

## Use cases

OptiPNG.js is particularly useful for:

* Optimizing user-uploaded PNG images before submission
* Reducing bandwidth usage in image-heavy web applications
* Creating efficient image processing workflows
* Implementing client-side image optimization in static site generators

<span aria-hidden="true" id="conclusion"></span>

## Conclusion

OptiPNG.js provides powerful client-side PNG optimization capabilities, enabling developers to reduce image file sizes without compromising quality. By implementing proper error handling and leveraging Web Workers, you can create robust image optimization solutions directly in the browser.

For server-side image optimization needs, consider using Transloadit's[/image/optimize](/docs/robots/image-optimize.md) robot, which includes OptiPNG among its optimization tools.

\#javascript-image-optimization#browser-image-optimization#web-performance#image-processing#image-processing-service#image-optimize-robot

### 👩‍💻 Join 20k+ developers

Sign up for our [monthly newsletter](/newsletters.md) to receive direct links to 3 exclusive tech — and 2 product updates. No less, no more.

Your email:

Get access

## File uploading and encoding. Made simple.

Transloadit streamlines file handling for developers, trusted by brands like Coursera and The New York Times. We’re known for a reliable API, top-notch support, and a strong commitment to open source, with projects like [Uppy⁠](https://uppy.io) and [Tus⁠](https://tus.io) setting standards in file processing.

[Sign up](/c/)[Book a Demo](https://survey.typeform.com/to/kRg47Xi5)

No credit card needed · 5 GB included in the free plan

Cancel anytime
