npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

picscrub

v1.1.1

Published

Remove EXIF, GPS, and other metadata from images. Supports JPEG, PNG, WebP, GIF, SVG, TIFF, HEIC, and RAW formats.

Readme

PicScrub

Remove EXIF, GPS, and other metadata from images. Fast, lossless, zero dependencies.

Try it online at picscrub.com — no install needed, runs in your browser.

npm version License: MIT

Why PicScrub?

When you share photos online, they often contain hidden metadata that reveals:

  • GPS coordinates - Exact location where the photo was taken
  • Device information - Camera model, serial numbers
  • Timestamps - When the photo was taken
  • Personal info - Author name, copyright, comments
  • Thumbnails - Embedded preview images that may contain edited-out content

PicScrub removes all this metadata through direct binary manipulation, without re-encoding the image.

Features

  • 9 formats - JPEG, PNG, WebP, GIF, SVG, TIFF, HEIC, DNG, RAW
  • Fast - Binary manipulation, no re-encoding
  • Lossless - Preserves image quality perfectly
  • Tree-shakeable - Import only what you need (~50KB core)
  • TypeScript - Full type definitions included
  • Zero dependencies - No external runtime dependencies

Installation

npm install picscrub

Quick Start

import { removeMetadata } from 'picscrub';

// From file input
const fileInput = document.querySelector('input[type="file"]');
fileInput.addEventListener('change', async (e) => {
  const file = e.target.files[0];
  const buffer = await file.arrayBuffer();

  const result = await removeMetadata(new Uint8Array(buffer));

  console.log(`Format: ${result.format}`);
  console.log(`Removed: ${result.removedMetadata.join(', ')}`);
  console.log(`Size: ${result.originalSize} -> ${result.cleanedSize} bytes`);

  // Download cleaned image
  const blob = new Blob([result.data], { type: `image/${result.format}` });
  const url = URL.createObjectURL(blob);
  // ... use url for download or display
});

Node.js / CLI

File API

Process image files directly on disk:

import { processFile } from 'picscrub/node';

// Creates photo-clean.jpg alongside the original
const result = await processFile('photo.jpg');

// Overwrite the original
await processFile('photo.jpg', { inPlace: true });

// Custom output path
await processFile('photo.jpg', { outputPath: 'clean/photo.jpg' });

// Custom suffix
await processFile('photo.jpg', { suffix: '-stripped' });

// With preserve options
await processFile('photo.jpg', {
  preserveOrientation: true,
  preserveColorProfile: true,
});

CLI

# Process files (creates *-clean.* versions)
npx picscrub photo.jpg

# Process multiple files
npx picscrub *.jpg

# Overwrite originals
npx picscrub -i photo.jpg

# Custom output
npx picscrub -o clean.jpg photo.jpg

# Preserve orientation
npx picscrub --preserve-orientation photo.jpg

Options:

| Flag | Description | |------|-------------| | -i, --in-place | Overwrite original files | | -o, --output <path> | Output file (single file only) | | -s, --suffix <suffix> | Output suffix (default: "-clean") | | --preserve-orientation | Keep EXIF orientation tag | | --preserve-color-profile | Keep ICC color profile | | --preserve-copyright | Keep copyright notice | | -q, --quiet | Suppress output | | -h, --help | Show help | | -v, --version | Show version |

API Reference

removeMetadata(input, options?)

Remove metadata from an image.

const result = await removeMetadata(imageBytes, {
  preserveOrientation: true,   // Keep EXIF orientation (rotation)
  preserveColorProfile: true,  // Keep ICC color profile
  preserveCopyright: true,     // Keep copyright notice
  preserveTitle: true,         // SVG: Keep <title>
  preserveDescription: true,   // SVG: Keep <desc>
});

Returns:

interface RemoveResult {
  data: Uint8Array;          // Cleaned image
  format: SupportedFormat;   // Detected format
  originalSize: number;      // Before (bytes)
  cleanedSize: number;       // After (bytes)
  removedMetadata: string[]; // What was removed
}

detectFormat(data)

Detect image format from binary data.

import { detectFormat } from 'picscrub';

const format = detectFormat(imageBytes);
// 'jpeg' | 'png' | 'webp' | 'gif' | 'svg' | 'tiff' | 'heic' | 'dng' | 'raw' | 'unknown'

getMetadataTypes(data)

Get list of metadata types without removing them.

import { getMetadataTypes } from 'picscrub';

const types = getMetadataTypes(imageBytes);
// ['EXIF', 'XMP', 'ICC Profile', 'GPS']

Supported Formats

| Format | Metadata Removed | Quality Impact | |--------|------------------|----------------| | JPEG | EXIF, XMP, IPTC, ICC Profile, Comments, Adobe | None | | PNG | tEXt, iTXt, zTXt, eXIf, iCCP | None | | WebP | EXIF, XMP, ICCP | None | | GIF | Comments, XMP, Application Extensions | None | | SVG | metadata, RDF, comments, editor namespaces | None | | TIFF | EXIF, GPS, XMP, ICC Profile | None | | HEIC | EXIF, GPS, Thumbnails, MakerNotes | None* | | DNG | Full TIFF-based metadata | None | | RAW | Extracts clean JPEG preview | Preview only |

*HEIC uses lossless anonymization - metadata is overwritten with zeros rather than removed.

Known Limitations

TIFF Format

  • Basic TIFF files are fully supported
  • Complex TIFF structures may have limitations:
    • Multi-page TIFFs: Only the first IFD is processed
    • Tiled images: May not preserve all tile offsets correctly
    • Complex offset chains: Files with multiple IFDs and intricate offset dependencies may not process correctly
  • Recommendation: Test with your specific TIFF files before production use

HEIC Format

  • Uses "lossless anonymization" approach for safety
  • Metadata is overwritten with zeros, not removed
  • File size remains the same (metadata bytes become zeros)
  • Image data (HEVC stream) is completely preserved
  • Embedded thumbnails are destroyed (overwritten with pattern data)
  • This approach ensures file structure integrity without complex offset recalculation

RAW Formats

| Format | Handling | Output | |--------|----------|--------| | DNG | Full TIFF-based processing | Clean DNG file | | CR2 (Canon) | JPEG preview extraction | Clean JPEG | | NEF (Nikon) | JPEG preview extraction | Clean JPEG | | ARW (Sony) | JPEG preview extraction | Clean JPEG |

  • DNG: Fully supported using TIFF processing (DNG is TIFF-based)
  • Proprietary formats (CR2, NEF, ARW): Returns cleaned embedded JPEG preview
    • Original RAW sensor data is not preserved in output
    • Full-resolution JPEG is extracted from the embedded preview
    • Use this for sharing previews, not for archiving RAW files

How It Works

PicScrub operates directly on the binary structure of image files:

  • JPEG: Removes APP1-APP14 segments (EXIF, XMP, IPTC, ICC, Comments)
  • PNG: Filters out text chunks (tEXt, iTXt, zTXt) and EXIF chunks
  • WebP: Removes EXIF/XMP chunks and updates VP8X header
  • GIF: Removes comment and application extension blocks
  • SVG: Regex-based parsing, removes metadata elements and editor attributes
  • TIFF: Filters IFD entries to remove metadata tags
  • HEIC: Overwrites EXIF/thumbnails with zeros (preserves structure)

No image re-encoding ocurrs - pixel data is never touched.

Advanced Usage

Format-Specific Handlers

import { jpeg, png, webp, gif, svg, tiff, heic, raw } from 'picscrub';

// Use format-specific handlers directly
const cleaned = jpeg.remove(jpegBytes, { preserveOrientation: true });

File Signatures

import { FILE_SIGNATURES } from 'picscrub';

// Access magic bytes for format detection
console.log(FILE_SIGNATURES.JPEG); // Uint8Array([0xff, 0xd8, 0xff])
console.log(FILE_SIGNATURES.PNG);  // Uint8Array([0x89, 0x50, ...])

Binary Utilities

import { buffer, dataview, crc32 } from 'picscrub';

// Low-level binary operations
const data = buffer.concat(header, body, footer);
const value = dataview.readUint32BE(data, offset);
const checksum = crc32(data);

Browser Support

  • Chrome 89+
  • Firefox 89+
  • Safari 15+
  • Edge 89+

Requires TextEncoder, TextDecoder, and Uint8Array support.

Security Considerations

  • Input validation prevents buffer overflow attacks
  • No eval() or new Function() used
  • Safe for use with user-uploaded content

Acknowledgments

This project is a modernized fork of exif-library by @hMatoba. The original library provided excellent JPEG/PNG/WebP EXIF handling that served as the foundation.

What's new:

  • Modern TypedArray-based binary handling (no string manipulation)
  • Added GIF, SVG, TIFF, HEIC, and DNG/RAW support
  • Complete metadata removal (XMP, IPTC, ICC profiles, comments)
  • Lossless HEIC anonymization
  • TypeScript strict mode with full type definitions
  • Comprehensive test suite

License

MIT - see LICENSE for details.