Keep the original and identify the file you are checking

Download the original PNG or use the untouched output from your own generator. This guide's sample is a generated still life, preserved on August 21, 2026. We rechecked its bytes and the derivative files on October 1. An image saved from a preview, copied from a document, or received through a messaging service may already be an export.

Keep the source in a separate folder and write edits to new filenames. Record where you obtained it and its SHA-256 hash. A matching hash identifies the same bytes with overwhelming confidence; it does not identify the photographer, grant permission to use the image, or verify a caption. If a supplier sends a replacement original, keep both versions and their acquisition records.

The original sample has this hash:

68238924e488753bfc1883c0d1491f9407d87e39ad8fb550b0f9e762ce90c56e

The inspection script calculates this value for you. Compare it with the retained record before interpreting differences between runs. If your downloaded original has different bytes, investigate the download or export first.

Check an image without writing code

A C2PA manifest is a signed record of claims about a file, such as how it was created or edited. The Content Credentials Verify viewer lets you inspect those claims in a browser. Start with this guide's public demonstration file so you can compare a known result before checking your own image.

  1. Download the original PNG linked above. Use the file download rather than a screenshot of the picture.
  2. Open Verify and choose Select a file from your device. Select that PNG and wait for its details.
  3. Read Content summary. For this sample, the viewer displayed an AI-generation statement. This is a declaration in the credential; it is not a visual detector's guess.
  4. Read Process and its Actions. The sample showed Created and Format converted. Then read About this Content Credential and Issued by; this sample named OpenAI Media Service and OpenAI OpCo, LLC.
  5. Save the displayed result and date with the filename. Repeat with your cropped or exported file, then compare the two results. A result about the original cannot stand in for a check of the export.
Content Credentials Verify showing the original sample, creation actions and OpenAI issuer details
Verify displayed the original sample’s AI-generation declaration, actions and issuer details on October 1, 2026. The badge is a separate result from the local checker’s trust report. Credit: Content Credentials Verify interface; screenshot by Grow AI Skills. Open full-size image.

The original also displayed a Conformant badge on October 1, 2026. Its information panel described C2PA conformance and trust-list requirements. That badge does not verify the depicted scene or establish permission to use the image. The local check below reported unresolved signer trust for the same bytes, so keep each tool's result with its settings rather than treating the badge and a JSON status as interchangeable.

If a viewer reports that it found no credentials, keep that message and inspect the original separately. If it shows an error or returns to the upload screen, the check is incomplete. Verify failed to load our cropped sample during this browser check; the local checker separately found no manifest in that file. For a viewer failure, try reloading and selecting the file again, or use the local route. Do not turn a loading error into an absence result.

The Python route saves file hashes, detailed validation results, creation actions, ingredient relationships, and input errors in JSON. Use it for several exports or when you need a record another person can check. It reads files without editing them or adding credentials.

Download the practice kit and extract it. It contains the checker, pinned requirement, sample files, failure examples, and expected results. You can also download the standalone checker.

Run the checker with recorded settings

Our sample checks used Python 3.13.2 and c2pa-python 0.37.7 on macOS 26.3. The library requires Python 3.10 or later; see the official Python repository for setup requirements. Open a terminal in the folder containing the extracted kit, then run these macOS commands:

cd ai-provenance-review-kit-v2
python3 -m venv .venv
.venv/bin/python -m pip install -r requirements.txt
.venv/bin/python c2pa-provenance-check.py samples/ai-provenance-original.png > original-check.json

Windows setup

In Windows Command Prompt, use these paths after extracting the kit. This follows Python's virtual-environment layout; the Windows route was not run in our macOS test.

cd ai-provenance-review-kit-v2
py -3 -m venv .venv
.venv\Scripts\python.exe -m pip install -r requirements.txt
.venv\Scripts\python.exe c2pa-provenance-check.py samples\ai-provenance-original.png > original-check.json

If py is unavailable, check python --version and use python -m venv .venv if it reports Python 3.10 or later. Calling the environment's Python directly avoids shell-activation problems. Windows users can inspect all supplied samples; recreating the sips exports requires a Mac.

If installation or inspection fails

For No module named c2pa, run the installation command with the same .venv Python that runs the checker. For a missing script or sample, check that you are inside the extracted folder and that the file exists at the supplied path. Quote paths containing spaces. A native-library or architecture error is a setup failure: retain the error, check the library's platform requirements, and use the viewer while resolving it. None of these errors says anything about the image's origin.

A successful command creates original-check.json in the working folder. Open it in a text editor and check inspection_status. An empty report after a Python traceback is not a completed inspection. For a standalone installation, install c2pa-python==0.37.7 and pass the actual paths to your downloaded checker and image.

By default, this checker disables remote-manifest retrieval and fresh online OCSP requests, while keeping content, signature, and trust verification enabled. It therefore reports a local inspection, not a fresh online revocation investigation or a search for credentials elsewhere. We supplied no custom trust certificates.

Inspect several files in one invocation:

.venv/bin/python c2pa-provenance-check.py \
  samples/ai-provenance-original.png \
  samples/ai-provenance-cropped.png \
  samples/ai-provenance-reencoded-q60.jpg > comparison.json

Each input gets its own record. An unreadable, empty, unsupported, or obviously mislabelled file produces inspection_error and leaves manifest_present unset. The program continues with the other inputs, writes the report, and exits with code 2 when an input could not be inspected. Exit code 0 means inspection completed; it is not permission to publish the image.

Separate presence, validity, and signer trust

Read inspection_status first. Then inspect manifest_present, manifest_location, validation_state, and validation_results. The checker supplies the following working categories; they are its reporting labels, not replacements for the SDK's native validation state.

What happenedWhat you can concludeNext action
No credentials found
JSON: absent
No manifest was found within this run's lookup settings.Obtain the original and investigate the export or another supported lookup route.
Valid record; signer trust unresolved
JSON: present_valid_trust_not_established
The SDK reports valid data, but signer trust is unresolved or not reported.Read the certificate and timestamp details; record the trust configuration.
Valid record; signer trusted by this verifier
JSON: present_valid_trusted
The active signer is trusted under the configured verifier, and no active non-trust failure was reported.Read the assertions and ingredients before attributing the claims.
Record found; validation needs investigation
JSON: present_with_validation_issues
A manifest was read, but its state or active validation details need investigation.Identify the exact failed check, including possible content-binding failures.
Inspection failed
JSON: inspection_error
The checker could not complete the inspection.Repair the input or environment and rerun; do not describe it as having no credentials.

The C2PA validation model distinguishes a Valid manifest from a Trusted manifest. Trust adds a requirement about the signing credential. A signer name shown in a report is not, by itself, proof that your verifier established that trust.

Read the original's actual claims and warnings

The original PNG returned Valid. Its generator information named OpenAI Media Service API, and its signature information named OpenAI Media Service with OpenAI OpCo, LLC as issuer. The detailed result also included these entries:

validation_state: Valid
success: claimSignature.validated
success: assertion.dataHash.match
failure: signingCredential.untrusted
informational: timeStamp.untrusted

The content hash and claim signature checks succeeded, but signer and timestamp trust were not established in this configuration. That combination is why the checker retains the detailed entries alongside the summary. It does not justify calling the signing certificate fake, and it does not justify saying the signer was trusted.

In manifest_summaries, the original's creation action declared trainedAlgorithmicMedia as its digital source type. This field records the signer's AI-generation claim. Read creation and editing actions together: a tool may have signed an edited image or a composite, and the latest signer need not be the original creator.

For an unfamiliar image, report the assertion as a signed claim and state the validation and trust result. The generator name does not recover a hidden prompt, identify every human contributor, or establish a commercial license. Check usage permission separately against the supplier or the applicable terms.

If a different verifier reports another trust result for these same bytes, compare its version, trust anchors, timestamp handling, and network settings. The SDK's Context and settings guide explains those controls. Obtain trust anchors independently through your chosen trust policy. Do not disable trust verification or allow-list an unknown certificate merely to produce a reassuring result.

Reproduce the crop, resize, and export comparison

Work in a new output folder. The first three transformations below each start from the original PNG. The final transformation starts from the JPEG just created. For sips -c and -z, the arguments are height followed by width.

mkdir -p derived
sips -c 800 1200 samples/ai-provenance-original.png --out derived/crop.png
sips -z 450 800 samples/ai-provenance-original.png --out derived/resize.png
sips -s format jpeg -s formatOptions 60 samples/ai-provenance-original.png --out derived/q60.jpg
sips -s format png derived/q60.jpg --out derived/roundtrip.png

.venv/bin/python c2pa-provenance-check.py \
  samples/ai-provenance-original.png \
  derived/crop.png derived/resize.png \
  derived/q60.jpg derived/roundtrip.png > derived-check.json

We reran these commands on October 1, 2026. All four outputs matched the supplied sample hashes, and the configured checker found no manifest in any of them. Their result does not establish what another editor, operating-system build, or publication platform will do. Compare your output dimensions and inspect each file rather than assuming an export setting preserves credentials.

FileOperationObserved result
Original PNGUntouched generated outputEmbedded; Valid; signer trust not established
Copied PNGSame bytes, different filenameSame hash and original validation result
Cropped PNGCenter crop to 1200 by 800No manifest found
Resized PNGResize to 800 by 450No manifest found
JPEGQuality-60 export from originalNo manifest found
Round-trip PNGPNG export from that JPEGNo manifest found
Modified-metadata PNGAdd a text chunk after signingManifest present; Invalid; content hash mismatch

Download the intermediate JPEG alongside the PNG samples. The result ledger records the sample hashes and validation details. Different export software can produce different bytes even when it produces the same dimensions and presence result, so save your own export's hash and report.

Understand a missing manifest versus a failed binding

The copy is a control: renaming or copying the original without changing its bytes preserved the result. The ordinary exports changed the file and removed the embedded record. A third case retained the record while changing data covered by its binding.

For that failure example, we inserted a valid PNG text chunk into a copy of the signed original. The image-data chunks were unchanged. The SDK still read the manifest but returned Invalid with assertion.dataHash.mismatch. Inspect the modified-metadata sample or recreate it with the kit's make-integrity-test.py.

This demonstrates why visual similarity and manifest presence are insufficient. A failed binding means the current file cannot be accepted as matching the signed content under that check. It does not tell you who changed it or whether the change was malicious. Retain the failing copy, request the earlier original, and inspect it separately before making an attribution.

The kit also includes an empty file, a text file incorrectly named as a PNG, and an unsupported text input. Those produce inspection errors rather than the derivative samples' absent result. The header check catches basic mismatches only; it is not a complete image decoder or a guarantee that every damaged container will be identified. Investigate a file that will not open even if a verifier returns no manifest.

Distinguish EXIF labels from signed claims

An ordinary Software field, filename, or prompt-like metadata string can provide a lead about an image's history. It does not establish who wrote it or whether it still describes the current file. Metadata tools can change ordinary fields; the ExifTool documentation describes reading and writing them.

C2PA adds a signature and a binding to the file. Checking those can reveal whether the signed record matches the current content, subject to the verifier's validation and trust rules. A software name inside a successfully validated signed assertion has a different evidentiary role from an editable software label. It remains the signer's claim; it does not establish every earlier step in the image's history.

If EXIF names an AI tool but no C2PA record is found, report that the file contains that metadata label and that signed provenance was not established. If a signed record and EXIF disagree, preserve both, examine creation and editing actions, and ask the supplier for the original. Neither deleting the label nor adding an AI label creates reliable provenance.

Check an editor's new provenance chain

An editor that supports C2PA can create a new signed manifest for an edited output and reference the original as an ingredient. The CAI introduction describes this relationship. We did not measure a re-signed editor export here; use these checks when evaluating your editor.

  1. Import the original file and enable the editor's documented Content Credentials export option, if available. Record the editor version and export settings.
  2. Inspect the exported file. Identify its active manifest and latest signer, then read its editing actions.
  3. Inspect ingredients and the other manifest_summaries. Determine whether the earlier record is present or referenced and whether ingredient validation reports a problem.
  4. Check the active output's content binding and the trust result for the relevant signers. A valid latest record does not eliminate an earlier ingredient warning.
  5. Keep the source and exported files with their hashes. Verify the published copy as well.

A generic metadata-preservation checkbox is not enough. An editor must produce a record that matches its changed output; copying an old manifest into new bytes can leave a failed binding. A newly signed file with no recoverable ingredient history may establish claims about that new file without establishing its earlier source. Describe the part of the chain you actually verified.

Inspect the website's delivered image

The publication stage can introduce another export. This page offers a useful real example: its full-size PNG matches the retained original, while its 800-pixel and 1400-pixel WebP preview files had no manifest detectable in our October check. The page's image markup offers those previews to browsers that support WebP. The preview and the downloadable original are separate files.

In Chrome, use the Network panel to find the delivered file:

  1. Open the page, press Control+Shift+J on Windows or Command+Option+J on Mac, and select Network.
  2. Reload with the panel open. Filter by Img, then select the request whose preview matches the picture.
  3. Read Headers and record its Request URL. Open that URL and save the image file. Keep the actual format, such as WebP; do not convert it to PNG while saving.
  4. Run the checker on the downloaded file. Repeat at mobile and desktop widths, reloading each time. Compare URLs and hashes; responsive markup or a CDN may supply different files.

If you already have the image element selected in the browser inspector, its currentSrc property identifies the selected image URL. The HTML src alone can miss a WebP or responsive candidate. Scroll a lazy-loaded image into view before checking its request.

If the preview loses credentials but you retain a validated original, provide an explicit original-file download and explain that the preview is an export. Keep the internal relationship between their hashes. Do not attach the original's validation result to the preview as though both files returned it. After changing image optimization settings, fetch the delivered output again; an older cached file can produce a different result from your new source.

Handle screenshots, forwarded copies, and absent credentials

For a screenshot or a forwarded image, ask for the earliest available source file and the tool or platform history. The current file may omit earlier records or contain a new record covering the screenshot itself. Inspect what it actually claims. Do not assume that a credential on a screenshot establishes the origin of everything visible inside it.

When an original has credentials but a later copy does not, you can document loss between those two known versions. When you possess only an unsigned copy, you cannot determine from that absence whether credentials were removed, never added, or preserved elsewhere. Your report should say that origin remains unresolved.

C2PA also supports externally stored manifests, and durable-credential systems can use watermarks or fingerprints to locate a stored record. The durable credentials documentation explains this additional lookup mechanism. It requires compatible systems and retained records; recovery is not guaranteed for an arbitrary image.

The checker defaults to local lookup. Its optional --allow-remote flag lets the SDK retrieve a manifest referenced by the file, and reports whether the result is embedded or remote. It does not run a watermark detector, perform a fingerprint search, or recover a missing original. Remote retrieval and a custom trust-anchor run are supported options whose live service behavior was not tested here.

For an unresolved image, continue with its publication history, source confirmation, and caption evidence. Record those as separate findings. Neither an absent manifest nor a successful credential lookup supplies a reliable percentage probability that a picture is AI-generated.

Keep a review record that another person can check

Use the kit's provenance-review-record.json to record the original and derivative filenames, hashes, source URLs, transformation settings, checker version, lookup settings, detailed failures, and your decision. An internal relationship between two hashes is an organizational record; it does not create an embedded cryptographic ingredient chain.

Write conclusions at the level your evidence supports. For this original: the verifier reported Valid with a matching content hash and an AI-generation creation assertion, while signer trust was not established. For the cropped copy: no manifest was found in the inspected file. For the metadata-modified copy: a manifest was present, but its content binding failed. Keep these outcomes separate from whether the image may be used and whether its caption is accurate.

Run .venv/bin/python replay-provenance-checks.py to compare the kit's supplied samples with its expected outcomes and hashes. Then repeat the original, export, and delivery checks on your own image. Save the JSON report next to the exact files you reviewed, and record any unresolved trust, missing source, or failed binding before approving the delivered version.