C2PA Labels for AI Images: 12 Steps, $5K Fines [2026]

Two laws that regulate AI image labeling took effect on the exact same day this year: the EU AI Act’s Article 50(4) transparency rule and California’s AI Transparency Act (SB 942) both became operative on August 2, 2026. Neither one cares whether you’re a solo creator posting on Instagram or a newsroom running a wire photo. If the image was generated or substantially altered by AI and it resembles a real person, place, or event, it needs a provenance trail. The technical standard behind almost all of that trail is called C2PA, short for the Coalition for Content Provenance and Authenticity, and most people using AI image generators have never opened one.

This tutorial walks through exactly how to check, add, preserve, and verify C2PA Content Credentials on AI-generated images, whether they come out of GPT Image, Adobe Firefly, Nano Banana, Seedream, Grok Imagine, or Midjourney (which, notably, still ships none of this by default). By the end you’ll have a working command-line setup, a Python script that audits an entire image library for missing manifests, and a repeatable publishing checklist that keeps you on the right side of both the EU and California rules.

Google · Preferred Sources

Don't miss new tech stories on Google

Add Tech Insider once in the Google app and our stories appear in your news suggestions.

Add Now

What C2PA Content Credentials Are, and Why They Matter Right Now

C2PA content credentials are a machine-readable manifest embedded directly in an image file’s metadata. The manifest can record who or what created the image, which tool generated it, when it happened, and what edits were applied afterward. The underlying specification has moved fast: C2PA 2.2 shipped in May 2025 with support for signing video streams, C2PA 2.3 followed in February 2026, and C2PA 2.4 landed in April 2026 adding JSON serialization and support for new asset formats. Unlike a caption or a watermark stamped across the corner of a photo, a C2PA manifest travels with the file itself and can be cryptographically signed, so it’s much harder to fake than a text label.

Adoption moved fast in 2025 and 2026. Adobe Firefly, Photoshop’s Generative Fill, and Illustrator’s Generative Recolor now embed Content Credentials into every image they produce, spanning the entire Creative Cloud suite. OpenAI followed with a layered provenance approach announced May 19, 2026: every image generated through ChatGPT, Codex, and the OpenAI API now carries both a C2PA manifest and Google’s SynthID invisible watermark, pairing two separate provenance systems on a single file. Anthropic joined the list on August 2, 2026, adding signed C2PA metadata across three file types produced by Claude’s image tools, plus an invisible text watermark. Hardware makers are in on it too, and not just camera brands: Google’s Pixel 10, released in September 2025, signs every photo by default using hardware-backed keys at the moment of capture, and Sony, Nikon, and Leica have added similar C2PA signing to their cameras, which is a separate but related use case: proving an image is real, not just labeling one as fake.

Not every tool plays along. Midjourney remains one of more than 6,000 members and affiliates the Content Authenticity Initiative counted as of February 2026, but as of Midjourney V8 in mid-2026, images downloaded from Discord or the web app still carry no C2PA manifest and no known invisible watermark. That’s a notable gap given how far the broader ecosystem has moved: by May 2026, 54 products from 31 companies had formally passed C2PA’s conformance program, with another 120-plus companies reportedly expressing interest in going through conformance testing. That gap is the whole reason this tutorial exists: you can’t rely on your generator to do the labeling for you, so you need to know how to check, and how to add credentials yourself when the tool doesn’t.

Why Detection Tools Still Struggle With Unmarked Images

It’s worth understanding why this matters beyond compliance paperwork. When an image carries a C2PA manifest or a SynthID watermark, verifying its origin is a lookup, not a guess. The manifest either exists and validates against a trusted certificate, or it doesn’t. That’s a binary, reliable answer.

Images with no provenance data at all put detection tools in a much weaker position. Without a manifest or an invisible watermark to check, a detector has to infer AI origin purely from visual patterns in the pixels themselves, texture artifacts, lighting inconsistencies, telltale signs in hands or text rendering, the kind of statistical fingerprints that generative models tend to leave behind. That approach is inherently probabilistic, and it gets less reliable every time a newer model closes the visual gap with real photography. A July 2026 technical review of Midjourney’s provenance gap put it plainly: because the tool ships no machine-readable indication of AI origin, anyone trying to verify a Midjourney image after the fact is stuck relying on visual guesswork rather than a definitive check.

This is the practical argument for doing the manual labeling work in Steps 6 through 8, even when it feels like extra friction. A pixel-based detector might flag your labeled GPT Image file and your unlabeled Midjourney file with similar confidence scores, or it might miss both, but a C2PA check will always tell the difference correctly, provided the manifest survived your export pipeline.

Prerequisites: What You Need Before You Start

This tutorial mixes free web tools with a light command-line setup. None of it requires a paid subscription, though a signed certificate for production use does carry an ongoing cost, which is covered in the pitfalls section below. Here’s what to have ready:

  • A computer running macOS, Windows, or Linux with a terminal or command prompt
  • Python 3.7 or newer installed (check with python3 --version)
  • pip, Python’s package manager (bundled with modern Python installs)
  • Homebrew if you’re on macOS and want the quickest CLI install path
  • A handful of test images: at least one from an AI generator that embeds C2PA by default (GPT Image, Adobe Firefly, or Claude) and one from a tool that doesn’t (Midjourney is the easy example)
  • A free account on any AI image generator you already use for image-generation steps
  • Basic comfort running terminal commands and editing a short Python script

No coding experience is required for Steps 1 through 4, which rely entirely on web tools and a single CLI utility. Steps 7 and 11 involve short Python scripts, but the full code is provided and explained line by line.

Step 1: Audit Which AI Image Generators You Already Use Embed C2PA

Before adding anything, find out what you’re starting with. Pull up the documentation page for every AI image tool in your current workflow and search for “C2PA,” “Content Credentials,” or “provenance.” Most vendors now publish this explicitly because regulators started asking, and since C2PA’s own conformance program launched in June 2025, a growing share back that claim up with formal test results rather than marketing copy alone. If you’re not sure which generators belong in this audit, our rundown of the best AI image generators is a good starting point. The table below summarizes where the major tools stood as of September 2026, based on vendor announcements and independent C2PA adoption tracking.

AI Image ToolC2PA ManifestInvisible WatermarkAuto-EmbeddedNotes
OpenAI GPT Image / ChatGPT / CodexYesYes (SynthID)YesLayered provenance since May 19, 2026
Adobe Firefly / Photoshop Generative FillYesNo dedicated watermark disclosedYesDescribed as the most complete implementation across Creative Cloud
Anthropic Claude image outputYesYes (invisible text watermark)YesAdded August 2, 2026
Midjourney (V8)NoNo known watermarkNoCAI member, but ships no manifest as of mid-2026
Nano Banana, Seedream, Grok Imagine, and smaller toolsVariesVariesInconsistentCheck each vendor’s docs directly; support is not standardized across the smaller-tool tier

If your generator embeds credentials automatically, your job in the rest of this tutorial shifts from “add a manifest” to “make sure nothing strips it out later.” If it doesn’t, you’ll need Steps 6 through 8 to add one manually before you publish.

Step 2: Know the Legal Deadlines You’re Working Against

Two rules matter most right now, and both are already in force. The European Commission’s transparency package, tied to the EU AI Act’s Article 50(4), took effect August 2, 2026. It requires that AI-generated or manipulated content resembling real people, places, or events be clearly and visibly labeled, with a set of standardized icons the Commission created for that purpose, alongside machine-readable marking such as C2PA.

California’s AI Transparency Act (SB 942) took the same operative date, and it’s more specific about mechanics. Any covered provider (a generative AI system with more than one million monthly visitors or users, publicly accessible in California) must offer a free public detection tool, a user-selectable visible label option, and mandatory latent (invisible, machine-readable) disclosure embedded in every generated image, video, or audio file. That latent record has to include the provider’s name, the system name and version, a timestamp, and a unique identifier. Civil penalties run $5,000 per violation, with each day of non-compliance counted separately. The rule made headlines the day it kicked in when reporters noted Midjourney had no watermark in place as fines started.

RuleJurisdictionEffective DateWho’s CoveredCore RequirementPenalty
EU AI Act, Article 50(4)European UnionAugust 2, 2026Deployers of AI systems producing deepfake-style contentVisible label + machine-readable mark (C2PA is the recommended standard)Set by member-state enforcement bodies
California AI Transparency Act (SB 942)California, USAAugust 2, 2026Generative AI providers with 1M+ monthly users, public in CaliforniaFree detection tool + visible manifest label + mandatory latent disclosure$5,000 per violation, per day

If you’re publishing to a global audience, or you don’t know exactly where your readers are, the practical move is to treat both rules as the floor and label everything, everywhere.

Step 3: Install a C2PA Verification Tool

You have two options here, and it’s worth setting up both. The first requires no installation: the Content Authenticity Initiative’s own verification page lets anyone drag an image into a browser and see its manifest.

  • Go to contentcredentials.org/verify
  • Upload the image file directly (JPEG, PNG, and TIFF are supported)
  • Review the provenance panel that appears, which shows the generating tool, edit history, and signing certificate if present

The second option is c2patool, the open-source command-line utility maintained by the Content Authenticity Initiative on GitHub. It’s the tool you’ll want for batch work later in this tutorial. Install it with Homebrew on macOS, or download the prebuilt binary for your platform from the project’s GitHub releases page and place it on your system PATH.

# macOS via Homebrew
brew install c2patool

# Confirm the install and check your version
c2patool -V

If Homebrew isn’t available, download the archive matching your OS from the c2patool releases page, unzip it, and move the binary into a folder already on your PATH (/usr/local/bin on macOS and Linux is the usual spot).

Step 4: Verify Content Credentials on an Existing AI Image

With c2patool installed, run it against one of your test images. Use --info for a quick summary, or --certs if you want to see the signing certificate chain.

# Quick summary of any C2PA manifest present
c2patool gpt_image_test.jpg --info

# Extract the certificate chain used to sign the manifest
c2patool gpt_image_test.jpg --certs

# Full manifest tree, useful when an image has multiple edit generations
c2patool gpt_image_test.jpg --tree

Run the same three commands against your Midjourney test image. If your generator audit in Step 1 was accurate, the GPT Image file returns a populated manifest with a signing certificate, and the Midjourney file returns nothing, or an error stating no C2PA data was found. That contrast is the entire problem this tutorial solves.

Step 5: Generate Images With Native Provenance Support When You Can

The easiest compliance path is picking a generator that already does the work. If your project doesn’t require a specific tool’s visual style, favor GPT Image, Adobe Firefly, or Claude’s image output for anything headed to a publication, an ad campaign, or a regulated industry like finance or healthcare marketing. All three embed C2PA automatically, and GPT Image adds SynthID on top, which lets Google Search, Chrome’s “About this image” panel, and other SynthID-aware detectors confirm authenticity independently of the file’s metadata. If you’re still refining prompts before you generate, our guide on writing AI image prompts pairs well with this step.

If your workflow depends on Midjourney’s particular aesthetic or another tool without native support, don’t abandon it. Move straight to Step 6 and treat manifest-adding as a mandatory post-processing step, the same way you’d run a spell-check before publishing text.

Step 6: Add C2PA Manifests to Images That Don’t Have Them

For images generated in tools without native C2PA support, Adobe’s Content Credentials panel in Photoshop or Lightroom is the most accessible way to attach a manifest after the fact. Import the unmarked image, open the Content Credentials panel, and fill in the disclosure fields, including a statement that the image was AI-generated and which tool produced it. Exporting from Photoshop with Content Credentials enabled writes the signed manifest into the file.

If you don’t have a Creative Cloud subscription, c2patool can write a manifest directly from the command line using a JSON definition file. This is the more technical path, but it’s free and scriptable, which matters once you’re labeling images in bulk rather than one at a time.

# manifest.json describes what gets embedded
cat > manifest.json << 'EOF'
{
  "claim_generator": "MyPublication/1.0",
  "assertions": [
    {
      "label": "c2pa.actions",
      "data": {
        "actions": [
          { "action": "c2pa.created", "softwareAgent": "Midjourney V8" }
        ]
      }
    }
  ]
}
EOF

# Sign the image with the manifest and write a new output file
c2patool midjourney_output.jpg -m manifest.json -o midjourney_labeled.jpg

Note that a manifest added this way is only as trustworthy as the certificate signing it. c2patool ships with a test certificate suitable for learning the workflow, but production use for a publication or business requires a certificate from a recognized certificate authority in the C2PA trust list, which is a paid step covered in the pitfalls section below.

Step 7: Read and Automate Manifest Checks With Python

Checking images one at a time through a website doesn't scale past a handful of files. The c2pa-python library wraps the same underlying Rust SDK that powers c2patool, and it's the tool to reach for once you're automating checks across a folder of assets.

# Install the Python bindings
pip install c2pa-python

Here's a minimal script that reads whatever manifest data exists in a single file and prints it as readable JSON:

import c2pa
import json
import mimetypes

def get_mime(path):
    mime, _ = mimetypes.guess_type(path)
    return mime or "application/octet-stream"

def read_manifest(path):
    with open(path, "rb") as f:
        reader = c2pa.Reader(get_mime(path), f)
        raw_json = reader.json()
        if not raw_json:
            return None
        return json.loads(raw_json)

result = read_manifest("gpt_image_test.jpg")
if result:
    print(json.dumps(result, indent=2))
else:
    print("No C2PA manifest found in this file.")

Run this against both of your test images from Step 4. You should see a full JSON manifest for the GPT Image file, and "No C2PA manifest found" for the untouched Midjourney file, matching what the CLI told you earlier.

Step 8: Add Visible Labels for Platform and Legal Compliance

A C2PA manifest satisfies the machine-readable half of both the EU and California rules, but the visible-label half still needs a separate, human-readable disclosure. California's SB 942 calls this the "manifest disclosure," a user-facing label distinct from the latent metadata. The EU's transparency package goes further and provides a standardized set of icons for exactly this purpose.

In practice, this means adding a visible caption or overlay to any AI-generated image before it goes out the door, worded plainly: "AI-generated with [tool name]" or "Image created with GPT Image, September 2026." For platforms like Instagram, TikTok, YouTube, and LinkedIn, use their native AI-content labeling options where available, since those tags are typically preserved through the platform's own re-encoding pipeline in a way a caption in your file's metadata is not. For a news article or blog post, a short line in the caption or credit line does the job. Neither of the two laws requires the visible label to be huge or intrusive, just clear and easy to notice at first glance.

Platform-by-Platform Labeling Cheat Sheet

C2PA metadata and visible labels behave differently depending on where you're publishing. Google Search, Meta's platforms, major stock photo libraries, and newsrooms actively check for C2PA credentials as of 2026, which means a properly labeled image gets treated differently in search and moderation systems than an unlabeled one. Here's how to handle the platforms most people publish to.

  • Instagram and Facebook (Meta): Meta reads C2PA metadata where present and applies its own "AI info" label automatically in many cases. Still add a visible caption disclosure yourself, since automatic detection isn't guaranteed to catch every generator, especially smaller or newer tools.
  • TikTok: Use the platform's built-in AI-generated content toggle when uploading. TikTok's own re-encoding pipeline is aggressive, so don't rely on your file's embedded C2PA manifest surviving the upload untouched; the native label is the more dependable signal on this platform.
  • YouTube: For thumbnails and video content built from AI images, use YouTube's altered-content disclosure setting in the upload flow. This applies at the video level, not per-image, so if only part of your thumbnail is AI-generated, disclose it anyway; partial AI content still falls under most platform policies.
  • LinkedIn: No dedicated AI-image toggle as robust as TikTok's exists here as of 2026, so a caption disclosure is your primary tool. Preserve the C2PA manifest in the uploaded file where you can, since LinkedIn's professional audience and B2B compliance context make provenance more likely to be scrutinized.
  • News organizations and stock photo sites: These are the strictest checkers. Expect submissions with missing or suspicious provenance to be rejected or flagged for extra review outright, rather than published with a label added after the fact. Run the Step 4 verification check before submission, not after.
  • Your own website or CMS: This is the one channel where you have full control. Preserve the manifest through your CMS's image-processing pipeline (Step 9 covers exactly how to test for this), and add a visible credit line in the caption or byline area.

Step 9: Preserve Metadata Through Export and Upload Pipelines

This is where most labeling efforts quietly fail. A C2PA manifest embedded correctly at generation time can be stripped by something as ordinary as opening the file in an image editor that doesn't support Content Credentials, converting the format, or running it through a compression tool before upload. Even Adobe's own compliance documentation warns that users who reprocess a properly labeled image through a non-C2PA-aware tool lose the metadata layer entirely, leaving only the pixels and whatever invisible watermark (if any) survives.

Build your export pipeline to check for this. If you're resizing or compressing images before publishing, use a tool that explicitly preserves C2PA data (recent Photoshop and Lightroom versions do this by default) rather than a generic batch-resize script that touches only pixel data. If you're not sure whether your pipeline strips metadata, run the before-and-after files through c2patool and compare.

# Compare manifest presence before and after your export step
c2patool original.jpg --info > before.txt
c2patool exported.jpg --info > after.txt
diff before.txt after.txt

If after.txt comes back empty or throws a "no manifest found" message while before.txt doesn't, your export step is the culprit, and it's time to swap that tool out.

Step 10: Test Detection With SynthID and Platform Checkers

For images generated through OpenAI's tools, there's a second layer worth testing independently of the C2PA manifest: Google's SynthID invisible watermark, which OpenAI began applying alongside C2PA on May 19, 2026. SynthID doesn't rely on file metadata at all, which means it can survive some transformations that would strip a C2PA manifest, like screenshotting or heavy recompression. Google Search and Chrome's "About this image" feature can both surface a SynthID detection result for a given image, giving you a second, independent check beyond the manifest itself.

Run both checks on any image before it goes to publication: the C2PA manifest check from Step 4, and a SynthID lookup if the image originated from an OpenAI tool. Treat a mismatch (SynthID says AI-generated, but the C2PA manifest is missing) as a signal that something upstream stripped your metadata, and go back to Step 9. Our walkthrough on how to test AI image generators covers a similar before-and-after comparison method if you want to build this into a broader QA process.

Step 11: Automate Compliance Checks Across a Full Image Library

Once the manual workflow is solid, script it. The following expands the Step 7 reader into a batch auditor that walks a folder, checks every image for a manifest, and prints a simple compliance report. This is the core of the complete working project below.

import c2pa
import json
import mimetypes
import os
import sys

def get_mime(path):
    mime, _ = mimetypes.guess_type(path)
    return mime or "application/octet-stream"

def check_file(path):
    try:
        with open(path, "rb") as f:
            reader = c2pa.Reader(get_mime(path), f)
            raw = reader.json()
            return json.loads(raw) if raw else None
    except Exception:
        return None

def audit_folder(folder):
    labeled, unlabeled = [], []
    for name in os.listdir(folder):
        if not name.lower().endswith((".jpg", ".jpeg", ".png", ".tiff")):
            continue
        path = os.path.join(folder, name)
        manifest = check_file(path)
        (labeled if manifest else unlabeled).append(name)
    return labeled, unlabeled

if __name__ == "__main__":
    folder = sys.argv[1] if len(sys.argv) > 1 else "."
    labeled, unlabeled = audit_folder(folder)
    print(f"Labeled ({len(labeled)}):")
    for name in labeled:
        print(f"  [OK] {name}")
    print(f"\nMissing C2PA manifest ({len(unlabeled)}):")
    for name in unlabeled:
        print(f"  [MISSING] {name}")

Run it with python3 audit.py /path/to/your/images. The output splits your library into two lists, so you know exactly which files still need manual labeling from Step 6 before anything ships.

Step 12: Monitor and Audit Your Image Library Going Forward

Compliance isn't a one-time pass. New images enter your workflow constantly, generators update their provenance behavior without much warning (Anthropic's C2PA support only shipped in August 2026, months after Claude's image tools launched), and certificate revocations can invalidate manifests you thought were solid. Nikon's C2PA implementation, for example, was suspended earlier in 2026 after a signing vulnerability forced a full certificate revocation, meaning images signed under that certificate could suddenly fail verification.

Schedule the audit script from Step 11 to run on a regular basis, whether that's a weekly cron job on a content team's server or a manual run before each publishing cycle. Treat any newly "unlabeled" result on a file you previously verified as a signal to check for a certificate revocation or a pipeline change that started stripping metadata.

Common Pitfalls When Labeling AI-Generated Images

  • Assuming every "AI-aware" tool embeds C2PA. Vendor marketing sometimes implies broad provenance support that doesn't hold up under a direct manifest check. Verify with c2patool rather than trusting a product page.
  • Losing the manifest during a simple format conversion. Converting a JPEG with an embedded manifest to PNG, or running it through a generic online compressor, frequently strips the C2PA data without any warning.
  • Treating a visible caption as sufficient on its own. Both the EU and California rules expect machine-readable disclosure in addition to a human-readable label, not one or the other.
  • Skipping the certificate step for production use. A manifest signed with a test certificate is fine for learning the workflow, but a publication or business needs a certificate from a trust-list certificate authority, which is a recurring cost, not a one-time setup fee.
  • Forgetting that screenshots erase everything. A screenshot of an AI image carries no C2PA manifest and, depending on the tool, may not carry an invisible watermark either. If an image needs to travel through a screenshot step, re-attach a manifest afterward.
  • Not re-checking after a platform re-encodes the file. Some social platforms recompress uploaded images in ways that can affect embedded metadata. Test with a real upload rather than assuming your local file's manifest survives untouched.

Troubleshooting: Common C2PA Problems and Fixes

  • c2patool reports "no claim found" on an image you expected to be labeled. Confirm the file wasn't re-saved or re-compressed after generation. Re-download the original from the generator rather than a re-exported copy.
  • c2patool command not found after installation. Confirm the binary's location is on your system PATH with echo $PATH (macOS/Linux) and add the folder if it's missing.
  • c2pa-python fails to import with an error about a missing module. Reinstall with pip install --upgrade --force-reinstall c2pa-python, which resolves most binding mismatches from older cached installs.
  • Content Credentials Verify shows "unable to validate" instead of a clean pass. This usually means the signing certificate has been revoked or expired, not that the manifest itself is corrupted. Check the certificate issuer's status page.
  • Manifest exists but shows the wrong generating tool. This can happen when an image passes through multiple AI tools in a pipeline (generated in one, edited in another). Check the manifest tree with --tree to see the full chain of assertions rather than just the most recent one.
  • SynthID check returns no result for an OpenAI-generated image. SynthID detection tools sometimes lag behind very recent generations by a few minutes while the watermark propagates through the detection index. Retry after a short wait.
  • Uploading a manifest-carrying image to a platform strips it immediately. Some platforms process every upload through their own re-encoding step regardless of source. Rely on the platform's native AI-label feature in these cases instead of the embedded manifest alone.
  • Batch audit script skips files with no error message. Check the file extension filter in the script; unusual extensions like .jfif or uppercase .JPG may not match the lowercase check and need to be added explicitly.
  • Two different tools disagree about whether an image has a manifest. Confirm both tools are checking the same file and not a cached or re-exported copy; a single re-save between checks is enough to change the result.

Advanced Tips for Teams and Enterprises

For a content team publishing at scale, wire the audit script from Step 11 into your CI/CD or CMS pipeline so no image reaches a live page without a manifest check passing first. Treat it the same way you'd treat an automated accessibility or broken-link check: a gate, not an afterthought.

If you're licensing your own AI image generation system to third parties, note that California's SB 942 specifically requires covered providers to contractually bind licensees to preserve manifest and latent disclosure capability, meaning you can't simply hand off your model and disclaim responsibility for what downstream products do with the labeling. Build that language into licensing agreements now rather than after an audit flags it.

For teams handling sensitive or realistic depictions of real people, add a second layer beyond C2PA: a manual review step for any image resembling an identifiable person, since both the EU and California rules apply extra scrutiny to deepfake-style content specifically, separate from generic AI-generated images of objects or scenes.

Consider where your organization sits on the free-versus-paid tooling spectrum before scaling this beyond a handful of images. The table below breaks down the main options by cost and use case.

ToolCostBest ForLimitation
Content Credentials Verify (web)FreeOne-off checks, spot auditsNo batch processing; manual upload per image
c2patool (CLI, test certificate)FreeLearning the workflow, internal testingTest certificate isn't trusted for production publishing
c2pa-python + trust-list certificate~$289/year for CA trust infrastructureAutomated, production-grade batch signingRequires certificate management and renewal
Adobe Creative Cloud (Firefly, Photoshop, Lightroom)Subscription-basedTeams already in the Adobe ecosystemTies your workflow to Adobe's export pipeline specifically

For most individual creators and small teams, the free web tool plus the test-certificate CLI workflow covers everything through Step 11. The paid certificate only becomes necessary once you're signing manifests that need to be trusted by an outside party, such as a stock photo marketplace or a news wire service, rather than just verified internally. For a broader look at how these models compare on quality, pricing, and now provenance, see our AI models hub.

Complete Working Project: An End-to-End Compliance Checker

Combining everything above, here's a single script that audits a folder, flags unlabeled images, and generates a plain-text compliance report suitable for a publishing checklist or a compliance file. Save it as c2pa_audit.py.

import c2pa
import json
import mimetypes
import os
import sys
from datetime import datetime

def get_mime(path):
    mime, _ = mimetypes.guess_type(path)
    return mime or "application/octet-stream"

def check_file(path):
    try:
        with open(path, "rb") as f:
            reader = c2pa.Reader(get_mime(path), f)
            raw = reader.json()
            return json.loads(raw) if raw else None
    except Exception:
        return None

def summarize(manifest):
    if not manifest:
        return "no manifest"
    active_id = manifest.get("active_manifest")
    manifests = manifest.get("manifests", {})
    active = manifests.get(active_id, {}) if active_id else {}
    claim_generator = active.get("claim_generator", "unknown tool")
    return f"generated by {claim_generator}"

def audit_folder(folder):
    report_lines = [f"C2PA Compliance Report", "=" * 50]
    labeled_count, unlabeled_count = 0, 0
    for name in sorted(os.listdir(folder)):
        if not name.lower().endswith((".jpg", ".jpeg", ".png", ".tiff", ".jfif")):
            continue
        path = os.path.join(folder, name)
        manifest = check_file(path)
        status = summarize(manifest)
        if manifest:
            labeled_count += 1
            report_lines.append(f"[OK]      {name} - {status}")
        else:
            unlabeled_count += 1
            report_lines.append(f"[MISSING] {name} - needs manual labeling before publish")
    report_lines.append("=" * 50)
    report_lines.append(f"Total labeled: {labeled_count}  |  Total missing: {unlabeled_count}")
    return "\n".join(report_lines)

if __name__ == "__main__":
    target = sys.argv[1] if len(sys.argv) > 1 else "."
    report = audit_folder(target)
    print(report)
    with open("c2pa_compliance_report.txt", "w") as f:
        f.write(report)

Running python3 c2pa_audit.py ./published_images against a mixed folder produces output like this:

C2PA Compliance Report
==================================================
[OK]      hero_gpt_image.jpg - generated by OpenAI GPT Image
[OK]      product_firefly.png - generated by Adobe Firefly
[MISSING] concept_midjourney.jpg - needs manual labeling before publish
[OK]      relabeled_midjourney.jpg - generated by MyPublication/1.0
==================================================
Total labeled: 3  |  Total missing: 1

The script writes the same report to a text file, so it can be attached to a publishing ticket, dropped into a compliance folder, or checked into version control alongside the images it audits.

Frequently Asked Questions

Do I need to label AI images if I'm not a business, just a hobbyist?
California's SB 942 applies to covered providers, not individual users, so posting an unlabeled AI image to your personal account doesn't trigger the law directly. The EU's rule is broader and focuses on deployers of AI systems producing deepfake-style content, which can include individuals in some contexts. When in doubt, label it anyway; it costs nothing and avoids ambiguity.

Does every AI image generator support C2PA now?
No. OpenAI's tools, Adobe Firefly, and Anthropic's Claude embed it automatically as of 2026. Midjourney does not, as of version 8 in mid-2026. Support across smaller and newer tools varies and should be checked directly rather than assumed.

What's the difference between C2PA and SynthID?
C2PA is a metadata standard embedded in the file itself, readable by any C2PA-compatible tool. SynthID is Google's invisible watermark technology, woven into the pixel data rather than the metadata, which means it can survive some transformations (like screenshots) that would strip a C2PA manifest. OpenAI now applies both to its generated images.

Can I remove a C2PA manifest from an image?
Technically, yes, since running an image through a tool that doesn't preserve metadata will strip it, intentionally or not. Deliberately stripping provenance data from an image before publishing it as if it weren't AI-generated raises separate legal and ethical issues beyond the scope of this tutorial, particularly under the EU AI Act's deepfake disclosure rules.

Do I need a paid certificate to add C2PA manifests?
For learning and testing, no; c2patool ships with a test certificate. For production use by a publication or business, a certificate from a recognized certificate authority in the C2PA trust list is required, and that infrastructure carries an ongoing annual cost rather than being free.

Will adding C2PA data slow down my publishing workflow?
Minimally, once it's automated. The batch audit script in this tutorial checks an entire folder in seconds. The larger time cost is manual: fixing images that lost their manifest somewhere in your export pipeline, which is why Step 9's before-and-after check matters.

Does a visible "AI-generated" caption alone satisfy the legal requirements?
Not on its own. Both the EU transparency rules and California's SB 942 expect machine-readable disclosure (a C2PA manifest or equivalent) in addition to any visible label, not as a substitute for it.

What happens if a certificate authority revokes its signing certificate?
Images signed under a revoked certificate can fail verification even though the manifest content itself hasn't changed. This happened with Nikon's C2PA implementation in 2026 after a signing vulnerability forced a full certificate revocation. Re-run your audit script periodically to catch this kind of retroactive failure.

Related Coverage

Nadia Dubois

Nadia Dubois

AI & Innovation Editor

Nadia Dubois is the AI & Innovation Editor at Tech Insider, where she tracks the rapid evolution of artificial intelligence, from foundation models to real-world enterprise deployment. She previously covered AI and startups for La Tribune and contributed to MIT Technology Review's European coverage. Nadia specializes in generative AI, AI regulation, and the intersection of technology and European industrial policy. She holds a dual degree in Computational Linguistics and Journalism from Sciences Po Paris.

View all articles