What is this image?
An in-browser image-authenticity inspector for C2PA provenance, signatures, trust, and metadata.
I built this because image authenticity is often talked about as if it should produce one clean yes/no answer. That does not really match how provenance works, and it definitely does not match how images move around the internet.
The app is an in-browser inspector for the signals an image carries about its own origin. It reads C2PA Content Credentials, signature status, signer trust, edit history, and EXIF metadata without uploading the file anywhere.
It is not a real/fake oracle. A valid manifest can show who signed an image and whether the signed claims still verify cryptographically; missing credentials only mean that signal is absent, stripped, or never added.
What it does
The public surface is deliberately simple: drop in an image, keep the file on-device, and show the provenance and metadata signals the app can read.

The first analyser is C2PA. When an image has Content Credentials, the app reports the claim generator, listed edits, signature state, and trust state. When an image has no C2PA manifest, it falls back to EXIF hints such as camera make, model, software, and timestamps.

The important part is how the app phrases absence. “No credentials” does not mean “not AI,” and it does not prove the image is real. Screenshots, re-saves, crops, and platform processing often strip credentials before a person ever sees the file.
How it works
The app uses Svelte, Vite, @contentauth/c2pa-web, and exifr. The C2PA SDK runs in the browser through WASM, so the app can inspect the dropped file locally rather than sending it to a server.
The code path is small enough to reason about:
Dropzone -> File object -> analyze(file)
-> C2PA manifest read through c2pa-web
-> signature/trust classification
-> EXIF fallback when no manifest exists
-> ResultCard verdict

The trust-list setup mattered more than I expected. The app bundles both the current official C2PA trust list and the older interim trust-list resources under public/trust/, then serves them same-origin so the SDK can fetch them without CORS problems.
The interesting part
The trickiest part was separating signature validity from signer trust. Those sound similar, but they answer different questions.
A signature can be cryptographically valid while the signer is not in a loaded trust list. That means the file still matches the signed manifest, but the app cannot say the signer chains to a trusted anchor. A trusted result needs both pieces: the signature must verify, and the signer must chain to a recognised trust anchor.
The app keys that decision off validation_results.activeManifest.success, especially signingCredential.trusted, rather than the flat validation_status array. That distinction matters because the flat array can include an untrusted code from a CAWG sub-credential even when the primary signature is trusted.
Constraints that shaped it
I wanted the app to be private by default, so it had to work without upload. That ruled out a server-side verifier as the primary path and made the browser/WASM SDK the right fit.
I also wanted the UI to avoid false certainty. Provenance is useful evidence, but it is fragile evidence. The app needs to make room for several outcomes: signed and trusted, signed but untrusted, signed but unchecked, signature broken, no C2PA signal, and metadata-only hints.
The next checks need to follow that same shape. Watermarks, metadata, and source-history checks should add separate signals instead of collapsing everything into one verdict.
What I learned
Provenance work is mostly about careful language. The technical check is important, but the wording around the check decides whether a person treats the result as evidence or as a magic answer.
The other lesson was that browser-only verification is practical, but the setup details matter. WASM loading, worker setup, same-origin trust resources, file-type guards, and trust-list semantics all had to be boring before the UI could be useful.
What I left for later
The next obvious step is watermark detection, starting with SynthID and whatever other public detector APIs or local checks make sense. After that, source-history checks could help answer a different question: not “who signed this file,” but “where else has this image appeared?”
I also want more test images. A good inspector needs a small library of signed, trusted, untrusted, stripped, edited, and metadata-only files so changes to the analyser do not quietly change the meaning of the result.
Links
- Repo: https://github.com/DanSpicyTaco/what-is-this-image
- Main tools: Svelte, Vite,
@contentauth/c2pa-web,exifr, C2PA Content Credentials