# EU AI Act Article 50(2): marking AI-generated images with C2PA before the 2 December deadline

> Source: <https://dev.to/rulereddy/eu-ai-act-article-502-marking-ai-generated-images-with-c2pa-before-the-2-december-deadline-1opc>
> Published: 2026-10-27 14:38:20+00:00

If your product generates images, audio, video or text for people in the EU, Article 50(2) of the EU AI Act is the duty that lands on the engineering team, not the design team. It's not about a banner. It's about what travels inside the file.

This post walks through what the text says, the one transition date that matters, and a working pipeline that attaches C2PA Content Credentials to AI-generated images. It's readiness support for developers, not legal advice, and it was AI-assisted and then edited.

From [Regulation (EU) 2024/1689, Article 50](https://eur-lex.europa.eu/eli/reg/2024/1689/oj/eng), paraphrased closely:

Three things developers often get wrong:

If your image or audio feature launched before August, you have roughly five weeks from today. That's the reason for this post.

The Commission has also backed a voluntary [Code of Practice on Transparency of AI-generated Content](https://digital-strategy.ec.europa.eu/en/policies/code-practice-ai-generated-content), with a section for providers on marking and detection. It's worth reading alongside the [Commission's Article 50 guidelines](https://digital-strategy.ec.europa.eu/en/policies/guidelines-ai-transparency-obligations), because the regulation itself doesn't name a specific technology.

[C2PA](https://c2pa.org/) (Coalition for Content Provenance and Authenticity) is an open standard for signed provenance manifests, often called Content Credentials, embedded in or attached to media files. A manifest can record that an asset was created by a generative model, using the IPTC digital source type `trainedAlgorithmicMedia` from the [IPTC NewsCodes scheme](https://cv.iptc.org/newscodes/digitalsourcetype/).

It's a strong candidate for the "machine-readable" and "interoperable" parts of 50(2), but be honest about its limits:

Treat C2PA as one layer of your design, not the whole answer.

[`c2patool`](https://github.com/contentauth/c2pa-rs/tree/main/cli) is the open-source CLI from the Content Authenticity Initiative. Install a prebuilt binary from the [c2pa-rs releases](https://github.com/contentauth/c2pa-rs/releases?q=c2patool) or with `brew install c2patool` on macOS.

Save as `ai-generated.json`:

```
{
  "claim_generator_info": [
    { "name": "acme-image-service", "version": "2.3.0" }
  ],
  "title": "generated.jpg",
  "assertions": [
    {
      "label": "c2pa.actions",
      "data": {
        "actions": [
          {
            "action": "c2pa.created",
            "digitalSourceType": "http://cv.iptc.org/newscodes/digitalsourcetype/trainedAlgorithmicMedia"
          }
        ]
      }
    }
  ]
}
```

Use your own service name and version. The key line is `digitalSourceType` with the `trainedAlgorithmicMedia` code.

```
c2patool generated.jpg -m ai-generated.json -o generated.signed.jpg
```

The output extension has to match the input; the tool won't convert formats. Without a key and certificate configured, `c2patool` uses a built-in development certificate and prints a warning. That's fine for a spike and not fine for production. The project's docs say to keep private keys out of manifest files in production and use a subprocess or remote signer instead (see [signing docs](https://github.com/contentauth/c2pa-rs/blob/c2patool-v0.27.22/cli/docs/signing.md)).

```
c2patool generated.signed.jpg > report.json
jq -e '.. | objects | select(.digitalSourceType? | tostring | test("trainedAlgorithmicMedia"))' report.json \
  && echo "AI-source marker present" \
  || { echo "missing AI-source marker"; exit 1; }
```

Run this as a test on a sample output from every generation path you ship (image endpoint, batch export, editor "AI fill", and so on). The most common real-world gap isn't a missing library. It's one forgotten code path that writes files without the manifest.

A thin Node.js wrapper around the CLI:

``` js
import { execFile } from "node:child_process";
import { promisify } from "node:util";
const run = promisify(execFile);

export async function markAiImage(inPath, outPath) {
  await run("c2patool", [inPath, "-m", "ai-generated.json", "-o", outPath, "-f"]);
  const { stdout } = await run("c2patool", [outPath]);
  if (!stdout.includes("trainedAlgorithmicMedia")) {
    throw new Error(`C2PA marker missing on ${outPath}`);
  }
  return outPath;
}
```

`-f` lets the tool overwrite an existing output file. If you're in Rust, Python or JavaScript and don't want to shell out, the [C2PA SDKs](https://opensource.contentauthenticity.org/) expose the same builder.

Like any transparency duty, you'll want to show what you did, not just say it. A minimal record per release:

```
# compliance/art50-2-marking.yml
release: 2026-10-27
surfaces:
  - name: image-generation-api
    content: image/jpeg, image/png
    marking: c2pa manifest, digitalSourceType=trainedAlgorithmicMedia
    signer: remote (KMS-backed)
    ci_check: tests/c2pa_marker.sh
  - name: tts-export
    content: audio/mpeg
    marking: TODO (target before 2026-12-02)
known_gaps:
  - marker stripped when users screenshot output (evaluating invisible watermark)
```

It costs ten minutes and turns a vague "we're working on it" into a dated, reviewable plan.

This isn't legal advice or a compliance certification. Whether C2PA alone is "effective, interoperable, robust and reliable" enough for your product is a judgment for you and your counsel, informed by the Commission's guidelines and the Code of Practice.

If you're still working out which Article 50 paragraphs even apply to your product, RuleReddy has a free, no-signup [Article 50 check](https://www.rulereddy.com/eu-ai-act/tools/applicability-checker?utm_source=devto&utm_medium=article&utm_campaign=art50-50-2) that walks through the scoping questions.
