Skip to content
Back to skills

Strip Image Ai Metadata

ASecurity

Strip C2PA and AI-generation metadata from images (PNG, JPEG, WebP) and their .xmp/.json sidecars, to remove "Generated by AI" / "ChatGPT" / "DALL-E" labels that platforms like LinkedIn, Instagram, and X display. Use when the user wants to clean AI-generated images before posting, remove AI attribution from photos, strip C2PA manifests, sanitize image metadata for professional use, or verify whether an image contains C2PA data.

  • 3 stars
  • 0 votes
  • 0 copies
  • 4 views
  • Added September 19, 2026
ai-agentspythongobashgit

Security analysis

A100/100

Pro scans all 5 files and shows the line behind each finding

Scanned September 19, 2026

npx -y skills add getedgehq/skills --skill strip-image-ai-metadata --agent claude-code

Installs into .claude/skills of the current project.

Are you the author of Strip Image Ai Metadata?

Add the live security badge to your README. It updates with every re-scan.

Security grade badge for Strip Image Ai Metadata
[![Security: A — Skills Directory](https://www.skillsdirectory.com/api/skills/getedgehq-strip-image-ai-metadata/badge)](https://www.skillsdirectory.com/skills/getedgehq-strip-image-ai-metadata)

More formats (shields.io, HTML) on the badges page. Keep it an A: scan every change in CI with Pro.

Download with Pro
SKILL.md
---
name: strip-image-ai-metadata
description: Strip C2PA and AI-generation metadata from images (PNG, JPEG, WebP) and their .xmp/.json sidecars, to remove "Generated by AI" / "ChatGPT" / "DALL-E" labels that platforms like LinkedIn, Instagram, and X display. Use when the user wants to clean AI-generated images before posting, remove AI attribution from photos, strip C2PA manifests, sanitize image metadata for professional use, or verify whether an image contains C2PA data.
---

# Strip Image AI Metadata

Platforms like LinkedIn read C2PA metadata embedded by AI image generators (ChatGPT, DALL-E, Midjourney, etc.) and display an attribution label. This skill removes that metadata without re-encoding, so image quality is preserved.

## Supported formats

- **PNG**: removes `caBX` chunks, generator text chunks (`parameters`, `prompt`, `workflow` and friends) and AI-related `tEXt`/`iTXt`/`zTXt` chunks, and erases AI attribution tags inside `eXIf`
- **JPEG**: removes APP11 C2PA segments and AI-related APP1 (XMP) segments, erases AI attribution tags inside structured EXIF, and cleans the trailer after the `FFD9` end-of-image marker
- **WebP**: removes `C2PA` chunks and AI-related `XMP ` chunks, and erases AI attribution tags inside `EXIF`
- **Sidecars**: `.xmp` and `.json` files next to the image, or passed directly

## Quick use

Run the bundled script on one or more images:

```bash
python3 scripts/strip_c2pa.py image.png      # strips metadata + renames to IMG_YYYYMMDD_HHMMSS.png
python3 scripts/strip_c2pa.py image.jpg -o cleaned.jpg
python3 scripts/strip_c2pa.py *.png
python3 scripts/strip_c2pa.py photo.xmp      # a sidecar on its own
```

By default the script writes a cleaned copy with a neutral camera-style filename (`IMG_YYYYMMDD_HHMMSS.<ext>`) in the same directory and leaves the original untouched. Use `-i`/`--in-place` to overwrite the original, or `-o` for an explicit output path.

**Check the exit code.** `0` means the output is clean. `1` means something is still wrong and the file must not be published. Every failure is also printed.

## Workflow

1. **Inspect** (optional): If the user is unsure whether an image has C2PA metadata, run:
   ```bash
   strings -a image.png | grep -i c2pa
   ```
   or read PNG chunks with Python to look for `caBX`. `strings -a` matters: without `-a` some builds skip the trailer that follows the end-of-image marker, which is exactly where a hidden manifest lives.

2. **List the sidecars** before touching the image, so nothing is missed:
   ```bash
   ls -1 image.jpg.xmp image.xmp image.jpg.json image.json 2>/dev/null
   ```
   The script finds these itself, but seeing them first tells you what the run should report.

3. **Strip**: Run `scripts/strip_c2pa.py <path>`. The script writes a neutral-named copy by default and reports what was removed, image and sidecars together.

4. **Verify**: The script scans every file it wrote for remaining C2PA/AI signatures. A leftover is reported as `FAILED` and exits `1`, not as a note to skim past. If that happens, do not publish the file. Inspect it with `exiftool -a -G1 -u <file>` and `strings -a <file>` and deal with whatever is left by hand before it ships.

## Sidecars

Lightroom, Capture One, Bridge and most generation UIs write provenance into a file *beside* the image: `photo.jpg` plus `photo.xmp`, or `photo.png` plus `photo.png.json`. A spotless JPEG shipped next to a sidecar naming the generator is not a clean result.

The script handles both naming conventions (`name.ext.xmp` and `name.xmp`, either case) automatically whenever it processes an image, and it accepts a sidecar as a direct argument.

- **XMP**: AI provenance is removed property by property. Anything in a `c2pa`/`contentauth` namespace goes, as do properties and attributes whose value names a generator (`xmp:CreatorTool="ChatGPT"`, `Iptc4xmpExt:DigitalSourceType` set to `trainedAlgorithmicMedia`, a `dc:description` that says "Generated with DALL-E 3"). A property left empty by that removal is dropped too. Everything else survives, including Lightroom `crs:` develop settings, ratings, keywords and `dc:creator`.
- **JSON**: generator keys (`parameters`, `prompt`, `workflow`, `sd_model`, `c2pa` and friends) are dropped, as is any key or string value naming a generator. The rest of the file keeps its structure.
- **Output naming**: the sidecar follows the image. `photo.jpg` plus `photo.xmp` become `IMG_20260915_120000.jpg` plus `IMG_20260915_120000.xmp`, so the pair stays matched. With `-i` both are rewritten in place.
- **Unparseable sidecar**: if the XML or JSON does not parse, the script refuses. It leaves that file untouched, prints `FAILED sidecar`, names any AI signatures it can still see in the raw bytes, and exits `1`. Delete the sidecar or fix it by hand; do not ship the pair.

If the image itself is already clean but a sidecar is not, the script still writes the cleaned pair and says so.

## The JPEG trailer after FFD9

`FFD9` ends the JPEG codestream. Bytes after it are invisible to every decoder, which makes them a convenient hiding place, and a C2PA manifest parked there is still read by the platforms this skill exists to defeat. `exiftool -all=` does not remove it either.

The script cleans that region:

- A C2PA JUMBF manifest box is removed.
- An appended image (MPO/MPF multi-picture, common on phones) carries real pixels, so it is cleaned recursively rather than dropped.
- Any other trailer data carrying an AI signature is dropped whole, with its byte count and the signatures found reported.
- A trailer with no AI signature is left alone.

To confirm by hand that nothing is hiding back there. `rfind` is used because an EXIF thumbnail contains its own `FFD9`, so the first one in the file is usually not the real end of image:

```bash
python3 - <<'PY'
from pathlib import Path
d = Path('image.jpg').read_bytes()
i = d.rfind(b'\xFF\xD9')
print('bytes after the final EOI:', len(d) - (i + 2))
print(d[i+2:i+200])
PY
```

## EXIF attribution

Structured EXIF is not deleted wholesale, because it carries orientation, colour and the embedded thumbnail. Instead the attribution tags are erased in place: `ImageDescription`, `DocumentName`, `Make`, `Model`, `Software`, `Artist`, `Copyright`, `UserComment`, the Windows `XP*` tags, `CameraOwnerName`, `LensMake` and `LensModel`, in IFD0, the Exif sub-IFD and the thumbnail IFD1.

A tag is only erased when its value names a generator, so `Artist: Jane Doe` and a real camera's `Make`/`Model` survive while `Software: DALL-E 3` does not. The value bytes are overwritten with zeros rather than merely unreferenced, so nothing is left for `strings` to find, and no bytes move, so orientation and the thumbnail stay valid. The EXIF block comes out exactly the same length.

To audit what is left:

```bash
exiftool -a -G1 -u -Software -Artist -ImageDescription -Copyright -UserComment -XP:all image.jpg
```

## What this does NOT do

- It does not remove visible watermarks baked into pixels.
- It does not touch EXIF tags outside the attribution list above, so a MakerNote, an ICC profile description or an APP13/APP14 record naming a generator survives. These affect rendering or are vendor-opaque, so they are reported rather than guessed at: the final scan flags them and exits `1`.
- It does not re-encode, so file size and image quality are unchanged (except for the removed metadata).
- It does not upload anything or call any network service.

## When to re-encode instead

If the platform still shows an AI label after stripping, the attribution might be baked into pixels or stored in a non-C2PA format. In that case, use ImageMagick to decode and re-encode:
```bash
convert input.png -strip output.png
```
This is lossless for PNG but may cause slight quality loss for JPEG. Note that `-strip` drops orientation too, so check that the result is not rotated.

Files in this skill

  • DERIVATION.json3.4 KB
  • EVALS.md13.6 KB
  • LICENSE10.5 KB
  • SKILL.md7.7 KB
  • scripts/strip_c2pa.py38.5 KB

Attribution

Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.

Comments

Loading comments…

Newsletter

Get the weekly list of safe new skills, and the ones we pulled.