Strip hidden metadata from images before sharing. GPS coordinates, device info, timestamps, thumbnails, Content Credentials. Gone. Fast, lossless, zero dependencies.
Try it online at picscrub.com · no install needed, runs in your browser.
npm install picscrubimport { 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 useconst result = await removeMetadata(imageBytes, {
preserveOrientation: true, // keep EXIF rotation
preserveColorProfile: true, // keep ICC profile
preserveCopyright: true, // keep copyright notice
preserveContentCredentials: true, // keep C2PA manifest
});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,
// }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' });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 nothingAll CLI flags
| 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 |
| 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.
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
preserveContentCredentialsto 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, ComfyUIworkflow, 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.
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
}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
}import { jpeg, png, webp, gif, svg, tiff, heic, raw } from 'picscrub';
const cleaned = jpeg.remove(jpegBytes, { preserveOrientation: true });Preserve options by format
| 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 |
TIFF
- 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
HEIC
- Metadata is overwritten with zeros, not removed. File size stays the same
- Image data (HEVC stream) is completely preserved
- Embedded thumbnail images (
thmbitems) are image content and are left in place - 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 |
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.
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 |
Chrome 89+ · Firefox 89+ · Safari 15+ · Edge 89+
Modernized fork of exif-library by @hMatoba, with added support for GIF, SVG, TIFF, HEIC, DNG/RAW, TypeScript strict mode, and comprehensive metadata removal.
0 comments
log in to comment.