Guides

    Why C2PA manifests die on upload

    A C2PA manifest is a hash over exact bytes, so re-encodes and screenshots kill it by design. How to find the hop in your pipeline where provenance is lost.

    Versely Team9 min read

    The most common mistake about Content Credentials is treating the manifest as metadata that rides along with a file — a tag, present or absent, that a well-behaved tool preserves and a careless one drops. If that were true, the fix would be to use better tools.

    It is not metadata that rides along. The manifest is a cryptographic claim about one exact sequence of bytes, and it stops being valid the moment those bytes change. Not because a tool was careless. Because that is what the claim says. A manifest that survived an edit and still asserted "unchanged" would be the broken thing.

    Once you hold that correctly, the behaviour everyone complains about stops being a bug report and becomes a design constraint you can plan around.

    The hard binding, plainly

    A C2PA manifest contains a set of assertions — what produced the asset, what actions were taken on it, in what order — and a signature over those assertions. It is attached to the asset by a hard binding: a hash computed over the asset's own bytes, included in what gets signed.

    Validation is therefore a comparison. Hash the file you have in front of you. Compare it to the hash inside the signed manifest. If they match, the manifest describes this exact file and nothing has touched it since signing. If they do not match, the manifest describes something else.

    There is no partial credit in that comparison. A hash does not know that a re-encode is benign and a face swap is not. It reports one bit: same bytes, or different bytes. This is tamper-evidence, and it was never going to survive an editing pipeline, because editing changes bytes and that is the definition of the operation.

    The current public spec family is C2PA 2.x, and none of the versioning changes this property. It is the foundation of the design, not an implementation detail waiting to be improved.

    Five operations that change the bytes

    Operation What it does to the asset Manifest outcome
    Re-encode or transcode Rewrites the entire bitstream and container Broken or stripped
    Screenshot or screen recording Produces an entirely new file from pixels only Gone. Nothing carries over
    Format conversion New container, usually new bitstream Broken or stripped
    Editing in a non-C2PA-aware tool Genuine content change, no manifest rewritten Broken, and not replaced
    Platform ingest Almost always a re-encode for delivery Broken or stripped, outside your control

    The last row is why the title of this post is about upload specifically. Major platforms re-encode on ingest as a matter of course, because their delivery pipelines need their own formats, bitrates and resolutions. That transcode is not hostile to provenance. It is not thinking about provenance at all. It is a video pipeline doing its job, and a hard binding does not survive contact with it.

    Which means the honest statement about a raw manifest is: even a perfect pipeline of your own, with every tool conforming and every export signed, hands the file to one more re-encode you do not control. Raw manifests routinely do not survive distribution, and no amount of discipline on your side changes that final hop.

    The second death: valid but untrusted

    There is a failure that looks nothing like the first and gets confused with it constantly. A manifest can be intact, the hash can match, the signature can verify, and the result can still be worth very little.

    A signature proves a specific key signed those assertions. It does not, by itself, tell you that the holder of that key is anyone you should believe. Anything can sign a manifest asserting anything about its own output, including "captured by a camera." Cryptography answers who signed, not whether they were telling the truth.

    That gap is what the C2PA Conformance Program and its trust list exist to close. Conforming products are assessed and listed, and certificates chain to authorities the ecosystem recognises. A validator can then distinguish three genuinely different results:

    • No manifest. Nothing to evaluate.
    • Manifest present, binding broken. The file has changed since signing.
    • Manifest present, binding intact, signer not recognised. The claim is internally consistent and comes from someone nobody has vouched for.

    The third case is the one people misread as success, because most consumer-facing indicators collapse it into a green tick. It is also the reason "our tool supports Content Credentials" is not a fact you can verify from marketing copy — the check is whether the product appears on the conforming-products list, not whether the vendor mentions the standard.

    Finding the hop where yours dies

    This is a bisect, and it is one of the few compliance questions that has a definite answer you can obtain in an afternoon.

    1. Establish the source state. Take one asset straight from generation, before anything else touches it. Inspect it. Is there a manifest at all? If the generating tool does not sign, everything downstream is moot and your problem is upstream, not in your editing.
    2. Export one artefact per stage. Not screenshots of a preview window. The actual file each stage produces: after import, after the first edit, after the final export, after whatever compression or transfer step sits between export and upload.
    3. Inspect each one in order. Record three things per stage: manifest present, binding valid, signer recognised. Those are three different columns and collapsing them is how people end up with the wrong culprit.
    4. The first stage where a column flips is your answer. In most pipelines it is not the editor people suspect. It is a transfer step: a chat app, a file-sharing service that re-compresses, an asset manager that normalises on ingest, or a "make this smaller before uploading" step somebody added months ago.
    5. Then check the upload. Download your own published post and inspect that file too. This is the step almost nobody runs, and it is the one that tells you whether the platform kept anything.

    Two practical notes for anyone bisecting inside an editor. Inspect the final export, not a preview render — they are different files produced by different passes, and in Versely specifically the editor runs an EDL timeline where preview: true gives a free 480p pass that carries a short per-user cooldown, while the final export is a separate render charged once regardless of how many clips are on the timeline. And fold the inspection into whatever pre-publish check you already run alongside aspect ratio and caption burn-in, because a diagnostic you run once tells you about one week's pipeline.

    The longer walk through a real pipeline covers what each hop does; what C2PA actually records on design files covers what is in the manifest to begin with.

    What to do once you know

    Three options, and only the third is honest for most teams.

    Make every tool conforming. Realistic for a closed pipeline where you control every step. Not realistic the moment a client, a contractor or a platform is involved.

    Re-sign at export. The strongest thing under your own control: whatever happened upstream, the file leaving your pipeline carries a fresh, valid manifest describing what you did. It still dies at the platform's re-encode.

    Accept that the manifest is one layer and add another. This is where Durable Content Credentials come in: a manifest plus a soft binding living in the pixels or in a fingerprint database, so a record can be recovered after the hard binding is gone. Those layers have their own failure modes rather than fixing the problem outright, and how invisible watermarking works and where it stops is the sober version.

    One consequence for compliance planning: because raw manifests do not reliably survive distribution, a manifest alone is a poor sole answer to a machine-readable marking obligation. Article 50 of the EU AI Act applied on 2 August 2026, with a December backstop for systems already on the market covering the marking limb only, and the Commission's position has been that no single technique currently meets the standard by itself. Where the manifest genuinely does work end to end is where a platform reads it at ingest and acts on it, and TikTok reading Content Credentials on upload is the clearest example of that happening in the seconds before a re-encode kills it.

    FAQ

    If the manifest breaks on every edit, why sign at all?

    Because "unchanged since signing" is exactly the claim you want for an unedited asset, and a broken binding after a genuine edit is a correct result rather than a failure. The manifest also carries the assertion history, so a conforming editor can write its own actions into a new manifest rather than leaving a gap. The failure is not that bindings break. It is pipelines that break them and put nothing in their place.

    Does a lossless trim preserve the manifest?

    No. Lossless refers to picture quality, not to the byte content of the file. A trim changes the asset, which changes the hash, which invalidates the binding. The distinction that matters to a hash is whether the bytes are identical, and after any trim they are not.

    Can I tell whether a platform stripped my manifest or an earlier step did?

    Yes, by bisecting as above. If the manifest is present and valid in the file immediately before upload, and absent in the file you download back from the platform, the platform's ingest is the culprit. If it was already gone before upload, it was you, and it is usually a transfer or compression step rather than the editor.

    Is a green "verified" indicator proof the content is real?

    No. At best it means a manifest validated against the file and chained to a recognised signer, which establishes that a known party signed a described history for these exact bytes. It does not establish that the history is true, that the depicted event happened, or that a downstream copy is the same file.