Build1 publisher3 min readPublished
Sparkpix.ai routes detector uploads around its own WebP re-encoder to keep AI labels intact
Sparkpix.ai's detector stores uploads up to 10 MB byte-for-byte because its own WebP re-encoder strips the C2PA and IPTC labels it reads. Chat apps and screenshots lose the same labels, so a missing label clears nothing.
The Engineer · Build desk

What happened
- A developer who builds sparkpix.ai published about 60 lines of Node.js TypeScript that read C2PA and IPTC AI-provenance labels straight from image bytes.
- The code reports whether a label is present and which generator it names, but it does not verify the C2PA signature, so a forged manifest would pass.
- The detector's upload path skips the site's WebP re-encoder and stores files up to 10 MB byte-for-byte; larger files are still compressed and the user is warned.
- When no label turns up, the detector sends the image to apimodels.app's ai-image-detector, a synchronous classifier built by the same author.
Compiled by The EngineerSomething wrong?How this is made
Why it matters
- constraint For images that arrive through social platforms, chat apps or screenshots, the metadata layer finds nothing and the pixel classifier carries the verdict alone.
- decision Any operator running a label check behind an image optimizer has to route detector uploads around it and pick a file size above which losing the metadata layer is accepted.
- exposure Anyone who writes a fake manifest into a file can get a positive result from the byte scan, so its AI flag cannot back a legal provenance claim.
- cost Every unlabelled image becomes a paid call at about $0.015, roughly $15 per 1,000 images, billed by a vendor the detector's author also runs.
Both labels live in metadata segments, and re-encoding an image drops those segments [12]. A C2PA manifest is the signed record defined by the Coalition for Content Provenance and Authenticity [4]. It sits in a JUMBF box: APP11 segments in a JPEG, a caBX chunk in a PNG, a C2PA chunk in a WebP [5]. OpenAI, Adobe Firefly and Microsoft embed one [4]. The IPTC label is an XMP field, Digital Source Type, which Google writes into Gemini and Imagen images [6].
The reader never parses those containers. It decodes the whole buffer as latin1 and runs substring searches over it [7]. C2PA counts as present if the text holds both "jumb" and "c2pa", or "caBX", or "C2PA" within eight characters of "jumb" [7]. For IPTC, trainedAlgorithmicMedia means created by a generative model and compositeWithTrainedAlgorithmicMedia means edited with one [6]. The longer value contains the shorter one. The composite test therefore has to run first, or every AI-edited photo is flagged as fully generated [8]. A test set built only from fully generated images would pass with the checks in either order [8].
The generator name comes from the C2PA claim, which is CBOR [9]. Version 2 claims store it as claim_generator_info with a name such as "ChatGPT". Version 1 claims use a single claim_generator string such as "Adobe_Photoshop/25.0 adobe_c2pa/0.7.6" [9]. The hand-written CBOR reader takes the string length from the type byte, from one following byte, or from two [10]. It returns null for strings over 200 bytes or ones that run past the end of the buffer [10]. When the C2PA path yields nothing, a regex match on "Made with Google AI" sets the generator to "Google AI" [9].
The author wrote that when either label is present, "the question is settled: the maker declared it." [17] With the signature unchecked, what the scan settles is that the file makes the claim. For legal provenance the post points readers to the official c2pa-rs or c2pa-node libraries [11]. In my view that is the right split for a triage tool, as long as the verdict text says the file claims AI origin.
The byte-for-byte path exists because of the site's own optimizer. Every upload is compressed in the browser and re-encoded to WebP before it reaches storage [12]. The author wrote that this is "right for an image editor and fatal for a detector" [13]. According to the post, the most common reason a detector finds no label is that the operator's own code stripped it [12].
Outside the operator's stack there is no bypass to build. Social platforms and chat apps strip labels the same way, and a screenshot creates a brand-new file [15]. For those images the classifier scores texture, noise and structure [16]. It also reads C2PA itself and returns a value between 0 and 1 [16]. The post was drafted with AI assistance, and its code comes from the sparkpix codebase, built on Next.js App Router and Node 24 [3].
What to watch
- An accuracy figure for apimodels.app's classifier on re-encoded images and screenshots, where it decides with no label to read.
- Signature verification through c2pa-rs or c2pa-node in sparkpix.ai's detector, which would turn a present label into a checked declaration.