Windows Errors? Fix Them Before They Spread
Repair common Windows errors and clear accumulated junk for a smoother, more stable PC - no reinstall needed.Free scan · no reinstallOutdated Drivers Are Slowing You Down
One free scan finds every outdated or missing driver and matches the right update for your exact hardware.Free scan · exact hardware matchiTechGuides is reader-supported. When you buy through links on our site, we may earn an affiliate commission. As an Amazon Associate I earn from qualifying purchases. Learn more
To read C2PA provenance data from an image in Node.js, install @contentauth/c2pa-node, pass the image bytes with a known mimeType to Reader.fromAsset, and then inspect the manifest store from reader.json() and the active manifest from reader.getActive(). Any IPTC Digital Source Type term you find describes how the image was made, such as generated by AI, edited with generative tools, edited by humans, captured by a camera, or composited. It is a claim recorded in the manifest, not a verdict on the image.
The package is documented in the c2pa-node README, which now lives in the c2pa-js monorepo. The Content Authenticity Initiative’s JavaScript library documentation reports that the repository was merged into that monorepo in June 2026. The guidance below reflects documentation accessed on 7 October 2026.
Before you start
- Package:
@contentauth/c2pa-node. Install it withnpm install @contentauth/c2pa-node. - Platform: The package uses a native binary. The README lists Node and native-binary platform prerequisites; check them against your operating system and architecture before you deploy.
- Status: The library is documented as an early version. Pin the version you test, and recheck the README when you upgrade.
Choose how the library receives the image
The Reader accepts an asset. You can give it the bytes you already hold in memory, or a file-backed asset that points at the file on disk. The two forms behave differently with large or untrusted input, so choose before you write the parser.
The Tool Desk
Outbyte Driver Updater FREEFix the driver behind crashes, sound loss and screen glitchesFind Drivers →Outbyte PC Repair FREERepair Windows errors before they cause bigger problemsFix Now →| Input form | What the README documents | Memory behavior | MIME type handling | Use it when |
|---|---|---|---|---|
Buffer: { buffer, mimeType } |
Accepted by Reader.fromAsset. |
The complete file is allocated in memory first. The size rejection is applied after that allocation, so it does not protect memory. | Supply mimeType whenever it is known. |
Small files that your application has already loaded and trusts. |
| File-backed asset | Documented in the README. Use the exact asset shape shown there for your installed version. | The README recommends this form for large or untrusted images, because the buffer path allocates the whole file before any size limit runs. | Supply mimeType whenever it is known. |
User uploads, large media, and any file you have not vetted. |
Buffer input
If the bytes are already in memory, read them with readFile from node:fs/promises and pass them with a MIME type. Do not treat a size check on a buffer as a defense against large uploads, because the bytes already exist when the check runs.
#1 Best Overall
File-backed input
For uploads, store the file to disk first, validate its size and type at the HTTP layer, and then open it through a file-backed asset. This keeps the full file out of your Node process heap before the library decides whether to accept it.
Why the MIME type matters
The README states:
Always supply
mimeTypewhen it’s known, as byte-based detection is slower than a direct lookup and can be unreliable, which could surface as more confusing errors later on.
Source: the c2pa-node README. If your application already knows the format from its upload form or from a trusted extension check, pass that value. Byte-based detection is the fallback, not the default.
Quick wins for a faster PC:
Clear out junk files and repair common Windows errorsFree Scan →Fix the driver behind crashes, sound loss and screen glitchesFind Drivers →Rank #2
Read the manifest store and the active manifest
The following sequence reads an embedded manifest from a JPEG. It is adapted from the example in the official API documentation.
- Install the package with
npm install @contentauth/c2pa-node. - Load the bytes with
readFile('image.jpg'), or prepare a file-backed asset for large or untrusted input. - Open the Reader with
await Reader.fromAsset({ buffer, mimeType: 'image/jpeg' }). The call is asynchronous. - Read the full manifest store with
reader.json(). This returns every manifest the file carries, so use it when you need the history. - Read the active manifest with
reader.getActive(). This is the manifest that describes the asset as it is now.
import { readFile } from 'node:fs/promises';
import { Reader } from '@contentauth/c2pa-node';
const buffer = await readFile('image.jpg');
const reader = await Reader.fromAsset({
buffer,
mimeType: 'image/jpeg',
});
const manifestStore = reader.json();
const activeManifest = reader.getActive();
console.log({ manifestStore, activeManifest });
The Reader can also report whether the manifest is embedded in the file or fetched from a remote URL. Check the README for the exact property names in your version, and record that fact alongside the result, because a remote manifest has a different trust path from one embedded in the file.
Find the source-type entries
The C2PA specification describes assertions as namespaced labels, commonly beginning with c2pa.. One manifest can contain several assertions, and more than one assertion can share the same type. Do not assume the manifest has one flat “AI label” property. Action records can include a digitalSourceType value, which is either an IPTC term or a C2PA-specific value.
Rank #3
Because the position of the field can change, a recursive search is more reliable than a fixed path. The helper below collects every digitalSourceType string it finds, and you can run it on the object returned by reader.getActive() for the current claim, or on reader.json() for the full history.
Recommended Free Tools
function collectDigitalSourceTypes(node, found = []) {
if (Array.isArray(node)) {
for (const item of node) collectDigitalSourceTypes(item, found);
} else if (node && typeof node === 'object') {
for (const [key, value] of Object.entries(node)) {
if (key === 'digitalSourceType' && typeof value === 'string') {
found.push(value);
} else {
collectDigitalSourceTypes(value, found);
}
}
}
return found;
}
The C2PA specification also says that its schema material is there to aid understanding and does not recommend that manifest consumers perform schema validation as a general reading step. Parse the fields you need and handle unexpected shapes gracefully rather than rejecting the whole file.
Map IPTC terms to their meanings
The IPTC Digital Source Type vocabulary describes “from which source a digital image was created.” Each term has its own definition, and the distinctions matter. The table lists the examples in the currently reviewed vocabulary at cv.iptc.org/newscodes/digitalsourcetype. The vocabulary contains more terms than these, so look up any term you do not list.
Rank #4
| Term | What the IPTC definition covers | Source category |
|---|---|---|
trainedAlgorithmicMedia |
Created using generative AI. | Generated media |
compositeWithTrainedAlgorithmicMedia |
Edited using generative AI, including generative fill or outpainting. | Generative edit |
humanEdits |
Augmentation, correction, or enhancement by humans using non-generative tools. | Human edit |
digitalCapture |
Captured from real life with a digital camera or recording device. | Capture |
composite |
A mix of several elements, which may or may not use generative AI. | Composite |
minorHumanEdits |
Retired. Use humanEdits. |
Retired term |
softwareImage |
Retired in favor of more specific terms. | Retired term |
Do not render every term as “AI-generated.” A humanEdits entry and a compositeWithTrainedAlgorithmicMedia entry are both edits, but only the second involves generative AI. Likewise, composite does not tell you whether generative AI was used. Treat it as a flag that the image combines several sources, then read the rest of the manifest for detail.
The lookup below uses a Map so that unknown or inherited property names cannot match by accident. It keeps the last path segment of a URI, so it handles both bare term names and full IPTC URIs.
Do these 3 things before closing this tab:
1Scan for outdated or missing drivers - takes under a minute2Clear out junk files and repair common Windows errors3Fix the driver behind crashes, sound loss and screen glitchesconst IPTC_SOURCE_TERMS = new Map([
['trainedAlgorithmicMedia', 'Created using generative AI.'],
['compositeWithTrainedAlgorithmicMedia', 'Edited using generative AI, including generative fill or outpainting.'],
['humanEdits', 'Augmentation, correction, or enhancement by humans using non-generative tools.'],
['digitalCapture', 'Captured from real life with a digital camera or recording device.'],
['composite', 'A mix of several elements, which may or may not use generative AI.'],
]);
const RETIRED_TERMS = new Map([
['minorHumanEdits', 'humanEdits'],
['softwareImage', null],
]);
function describeSourceType(value) {
const term = String(value).split('/').pop();
if (IPTC_SOURCE_TERMS.has(term)) {
return { term, status: 'current', meaning: IPTC_SOURCE_TERMS.get(term) };
}
if (RETIRED_TERMS.has(term)) {
return { term, status: 'retired', replacement: RETIRED_TERMS.get(term) };
}
return { term, status: 'unrecognized' };
}
Report unrecognized values as they are. A C2PA-specific value or a term added after your mapping was written is not an error in the file, and it should not be silently mapped to a general category.
Keep validation and trust separate
A manifest can be read without being verified, and a verified manifest can still come from a signer you do not trust. Keep three questions apart in your code and in your interface.
- Was the manifest parsed? The Reader returned the manifest store and the active manifest, so the assertions can be displayed.
- Did cryptographic validation pass? The library reports whether the manifest’s binding and signature checks produced a valid result. The C2PA specification describes hard bindings as the way a validator establishes that a manifest belongs with the asset and that the covered asset bytes have not changed.
- Is the signer trusted? This is a policy decision made by your application, using the trust settings you configure. A valid signature from an untrusted signer is not the same as a trusted one.
Configure verification and trust through Context, as described in the README. The README marks raw per-instance settings as deprecated, so avoid them in new code.
A decision table for user-facing output
| Manifest parsed | Cryptographic validation | Signer trusted under your policy | What to show |
|---|---|---|---|
| Yes | Passed | Yes | The source-type claim, labeled as a claim by a trusted signer. |
| Yes | Passed | No | The source-type claim, with a note that the signer is not in your trust policy. |
| Yes | Failed | Any | Do not present the source-type claim as verified. Show the validation failure. |
| No manifest found | Not applicable | Not applicable | State that no readable Content Credentials were found in the file. |
Handle failures and edge cases
- Wrong or missing MIME type: Byte-based detection can fail or produce errors that are harder to trace. If an upload fails to parse, check the MIME type you passed before you suspect the file.
- Oversized input: Apply your size limit before you load the file. With a buffer, the file is already in memory when a size rejection runs.
- Unrecognized or retired terms: Map them as described above and keep the raw value in your logs.
- Several source-type entries: Report each entry with its assertion context. Do not collapse them into one flag.
What a source-type label does not establish
A digitalSourceType entry is a provenance claim made by whoever built the manifest. It is not an AI detector. An image without a label has not been shown to be unedited or human-made, and an image with a generative label has not been shown to be fake or misleading. Present the claim, its validation result, and the signer’s trust status, and let the reader judge from those facts.
Keep the parser current
Both the library and the vocabulary change. Check three things when you upgrade or deploy:
- The c2pa-node README for the current API, input forms, Context settings, and platform prerequisites.
- The C2PA Technical Specification 2.0 for the assertion and hard-binding rules that your validation logic relies on.
- The IPTC Digital Source Type vocabulary for term status, since terms can be retired and replaced. Each term entry carries its own creation and modification dates.
Keep your term table in one module so that a vocabulary update changes one place in your code.
Quick Recap
Product prices and availability are accurate as of the date/time indicated and are subject to change. Any price and availability information displayed on Amazon at the time of purchase will apply.

