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.2.0

Published

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

Readme

PicScrub

Strip hidden metadata from images before sharing. GPS coordinates, device info, timestamps, thumbnails, Content Credentials. Gone. Fast, lossless, zero dependencies.

npm version bundle size License: MIT

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


Install

npm install picscrub

Usage

import { removeMetadata } from 'picscrub';

const result = await removeMetadata(imageBytes);

console.log(result.format);          // 'jpeg'
console.log(result.removedMetadata); // ['EXIF', 'XMP', 'ICC Profile', 'Content Credentials (C2PA)']
console.log(result.cleanedSize);     // smaller than result.originalSize
console.log(result.provenance);      // { aiGenerated: true, digitalSourceType: 'trainedAlgorithmicMedia', ... }

// result.data is a clean Uint8Array ready to use

With options

const result = await removeMetadata(imageBytes, {
  preserveOrientation: true,        // keep EXIF rotation
  preserveColorProfile: true,       // keep ICC profile
  preserveCopyright: true,          // keep copyright notice
  preserveContentCredentials: true, // keep C2PA manifest
});

Inspect AI provenance without changing the file

import { inspectProvenance } from 'picscrub';

const report = inspectProvenance(imageBytes);
// {
//   contentCredentials: true,                     // C2PA manifest present
//   digitalSourceType: 'trainedAlgorithmicMedia', // IPTC declaration (XMP or C2PA)
//   creatorTool: 'Midjourney',                    // xmp:CreatorTool / PNG Software
//   generatorHints: ['Creator tool: Midjourney'], // Stable Diffusion, ComfyUI, Midjourney...
//   aiGenerated: true,
// }

Node.js file API

import { processFile } from 'picscrub/node';

await processFile('photo.jpg');                          // creates photo-clean.jpg
await processFile('photo.jpg', { inPlace: true });       // overwrites original
await processFile('photo.jpg', { outputPath: 'out.jpg' });

CLI

npx picscrub photo.jpg           # creates photo-clean.jpg
npx picscrub *.jpg               # batch process
npx picscrub -i photo.jpg        # overwrite original
npx picscrub -o clean.jpg photo.jpg
npx picscrub --inspect image.png # report metadata and AI provenance, write nothing

| 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 | | --preserve-content-credentials | Keep C2PA Content Credentials manifest | | --inspect | Report metadata and AI provenance, write nothing | | -q, --quiet | Suppress output | | -h, --help | Show help | | -v, --version | Show version |

Supported Formats

| Format | What gets removed | |--------|-------------------| | JPEG | EXIF, XMP, IPTC, ICC Profile, Comments, C2PA (APP11 JUMBF), data after EOI (MPF secondary images, motion-photo video). The Adobe APP14 color-transform marker is kept: it holds no personal data and CMYK/YCCK images decode wrong without it | | PNG | tEXt, iTXt, zTXt, eXIf, iCCP, C2PA (caBX) | | WebP | EXIF, XMP, ICCP, C2PA | | GIF | Comments, XMP, Application Extensions, C2PA | | SVG | metadata, RDF, comments, editor namespaces, C2PA, and the metadata of raster images embedded as base64 data URLs | | TIFF | EXIF, GPS, Interoperability (whole sub-IFDs wiped), XMP, IPTC, Photoshop, ICC Profile, C2PA (tag 52545) | | HEIC | EXIF, GPS, MakerNotes, C2PA (uuid box or item) * | | DNG | TIFF metadata plus camera serial number, unique model, lens info, capture dates, DNGPrivateData, original RAW file name | | RAW | Extracts the largest decodable JPEG preview and cleans it ** |

All formats are lossless. Pixel data is never touched. *HEIC overwrites metadata with zeros rather than removing it (file size stays the same). **Proprietary RAW formats (CR2, NEF, ARW) return the cleaned embedded JPEG preview.

AI Provenance and Content Credentials

Images from AI generators and modern cameras carry provenance metadata alongside EXIF:

  • C2PA Content Credentials: a signed manifest (used by ChatGPT, Firefly, Gemini, Leica, Sony). It can embed a thumbnail of the original, the edit history, the software and device, and sometimes the creator's identity. picscrub removes it by default in every format; pass preserveContentCredentials to keep it.
  • IPTC Digital Source Type: the standard "this is AI-generated" flag inside XMP (trainedAlgorithmicMedia), written by ChatGPT, Midjourney, Firefly and Meta AI. Removed together with XMP.
  • Generator text: Stable Diffusion parameters, ComfyUI workflow, Midjourney job IDs in PNG text chunks or EXIF comments. Removed together with the text chunks.

inspectProvenance() and picscrub --inspect report what was found, and every RemoveResult carries the same report as provenance. Detection is container-level only: manifests are never parsed or verified.

Keeping a manifest with preserveContentCredentials keeps its bytes intact, but removing any other metadata usually breaks the manifest's hash binding, so validators may flag it as tampered.

What picscrub does not do: invisible pixel watermarks such as Google SynthID, Adobe TrustMark/Digimarc or Meta Stable Signature are not detected or removed. They live in the pixels, have no public decoder, and removing them requires lossy re-generation of the image. picscrub never modifies pixels.

API Reference

removeMetadata(input, options?)

Accepts Uint8Array, ArrayBuffer, or base64 data URL. Returns:

interface RemoveResult {
  data: Uint8Array;            // cleaned image
  format: SupportedFormat;     // detected format
  originalSize: number;        // before (bytes)
  cleanedSize: number;         // after (bytes)
  removedMetadata: string[];   // what was actually removed
  provenance: ProvenanceReport; // AI / Content Credentials declarations found in the original
}

detectFormat(data) / getMetadataTypes(data) / inspectProvenance(data)

import { detectFormat, getMetadataTypes, inspectProvenance } from 'picscrub';

detectFormat(imageBytes);      // 'jpeg' | 'png' | 'webp' | ... | 'unknown'
getMetadataTypes(imageBytes);  // ['EXIF', 'XMP', 'ICC Profile', 'Content Credentials (C2PA)']
inspectProvenance(imageBytes); // ProvenanceReport, see "AI Provenance and Content Credentials"
interface ProvenanceReport {
  contentCredentials: boolean; // C2PA manifest present
  digitalSourceType?: string;  // IPTC value, e.g. 'trainedAlgorithmicMedia'
  creatorTool?: string;        // xmp:CreatorTool or PNG Software
  generatorHints: string[];    // e.g. 'Stable Diffusion parameters', 'ComfyUI workflow'
  aiGenerated: boolean;        // metadata declares AI generation
}

Format-specific handlers

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

const cleaned = jpeg.remove(jpegBytes, { preserveOrientation: true });

| Option | JPEG | PNG | WebP | GIF | TIFF | HEIC | SVG | |--------|------|-----|------|-----|------|------|-----| | preserveOrientation | Yes | - | - | - | Yes | - | - | | preserveColorProfile | Yes | Yes | Yes | - | Yes | Yes | - | | preserveCopyright | Yes | - | - | - | Yes | - | - | | preserveContentCredentials | Yes | Yes | Yes | Yes | Yes | Yes | Yes | | preserveTitle | - | - | - | - | - | - | Yes | | preserveDescription | - | - | - | - | - | - | Yes |

Known Limitations

  • Multi-page TIFFs: only the first IFD is processed
  • Tiled images may not preserve all tile offsets correctly
  • Test with your specific TIFF files before production use
  • Metadata is overwritten with zeros, not removed. File size stays the same
  • Image data (HEVC stream) is completely preserved
  • Embedded thumbnail images (thmb items) are image content and are left in place
  • This approach ensures file structure integrity without complex offset recalculation

| 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 |

Proprietary formats (CR2, NEF, ARW) return the cleaned embedded JPEG preview. Original RAW sensor data is not preserved. Use for sharing previews, not for archiving.

How It Works

PicScrub operates directly on binary file structures. No re-encoding, no quality loss.

| Format | Technique | |--------|-----------| | JPEG | Removes APP1–APP15 segments (except the Adobe APP14 color marker), including APP11 JUMBF (C2PA), and everything after the EOI marker | | PNG | Filters metadata chunks (tEXt, iTXt, zTXt, eXIf, caBX) | | WebP | Removes EXIF/XMP/C2PA chunks, rebuilds the VP8X header with the original canvas size | | GIF | Removes comment and application extension blocks | | SVG | Regex-based removal of metadata elements and editor attributes; auto-generated ids are kept when referenced | | TIFF | Filters IFD entries, zeros removed values and the EXIF/GPS sub-IFDs they pointed to (image strips are never touched) | | HEIC | Overwrites EXIF/XMP items with zeros (in mdat or idat), retypes C2PA uuid boxes to free | | RAW | Scans for embedded JPEGs, keeps the largest decodable one, cleans it with the JPEG handler |

Browser Support

Chrome 89+ · Firefox 89+ · Safari 15+ · Edge 89+

Acknowledgments

Modernized fork of exif-library by @hMatoba, with added support for GIF, SVG, TIFF, HEIC, DNG/RAW, TypeScript strict mode, and comprehensive metadata removal.

License

MIT