ai-image-detector
v1.0.1
Published
Detect and verify AI-generated images — check C2PA, SynthID, OpenAI DALL-E, Adobe Firefly, Google Gemini, and Stability AI provenance through a single unified API
Maintainers
Readme
ai-image-detector
Detect & Verify AI-Generated Images — C2PA, SynthID, DALL-E, Firefly, Gemini, Stable Diffusion
A single npm package that detects and verifies AI-generated images across all major AI image generators — C2PA, SynthID, OpenAI DALL-E, Adobe Firefly, Google Gemini/Imagen, and Stable Diffusion — through one unified API.
⚠️ ai-image-detector does NOT attempt to visually detect AI-generated images.
It only verifies official provenance evidence — metadata, Content Credentials, watermarks, and cryptographic signatures embedded by AI providers themselves.
Why ai-image-detector?
Before this package, you needed multiple provider-specific integrations:
// ❌ Before
import providerA from "some-c2pa-library";
import providerB from "some-openai-metadata-tool";
import providerC from "custom-stable-diffusion-parser";With ai-image-detector:
// ✅ After
import { verifyImage, verifyC2PA, verifyOpenAI } from "ai-image-detector";Installation
npm install ai-image-detectoryarn add ai-image-detectorpnpm add ai-image-detectorRequirements: Node.js ≥ 20, ESM or CJS project.
Quick Start
import { verifyImage } from "ai-image-detector";
const result = await verifyImage("./photo.png");
console.log(result.verified); // true / false
console.log(result.confidence); // 0 – 1
console.log(result.providers); // ["Stability AI", "Metadata"]Example output
{
"verified": true,
"confidence": 0.9625,
"providers": ["Stability AI", "Metadata"],
"checks": {
"metadata": { "passed": true, "message": "Found AI-related PNG metadata chunks: parameters", "confidence": 0.85 },
"stabilityAI": { "passed": true, "message": "Stable Diffusion PNG parameter chunk found: key=\"parameters\"", "confidence": 0.97 }
},
"providerResults": [ ... ],
"verifiedAt": "2025-01-15T10:30:00.000Z"
}CLI
npx ai-image-detector photo.png
npx ai-image-detector photo.png --verbose
npx ai-image-detector photo.png --json
npx ai-image-detector https://example.com/image.jpgCLI output
╔══════════════════════════════════════╗
║ ai-image-detector • v1.0.1 ║
╚══════════════════════════════════════╝
✓ PROVENANCE VERIFIED via Stability AI, Metadata
Confidence ████████████████░░░░ 94%
Providers Stability AI · Metadata
Verified At 1/15/2025, 10:30:00 AM
Checks
────────────────────────────────────────────
✓ metadata (85%)
Found AI-related PNG metadata chunks: parameters
✓ stabilityAI (97%)
Stable Diffusion PNG parameter chunk foundCLI options
| Option | Description |
|--------|-------------|
| --json | Machine-readable JSON output |
| --verbose | Full per-provider check breakdown |
| --providers <names> | Comma-separated provider list |
| --timeout <ms> | Provider timeout (default: 10 000) |
| --metadata | Run only the Metadata provider |
| --c2pa | Run only the C2PA provider |
| --synthid | Run only the SynthID provider |
| --openai | Run only the OpenAI provider |
| --adobe | Run only the Adobe provider |
| --gemini | Run only the Gemini provider |
| --stability | Run only the Stability AI provider |
| --openai-key <key> | OpenAI API key |
| --adobe-client <id> | Adobe I/O client ID |
| --adobe-token <token> | Adobe I/O access token |
| --gemini-key <key> | Google Cloud API key |
| --synthid-key <key> | SynthID API key |
| --help | Show usage |
| --version | Show version |
API Reference
verifyImage(image, options?)
Runs all registered providers and returns an aggregated result.
import { verifyImage } from "ai-image-detector";
const result = await verifyImage("./image.png", {
providers: ["OpenAI", "Adobe"], // optional: run subset
timeout: 15_000, // optional: ms per provider
parallel: true, // optional: default true
includeMetadata: true, // optional: default true
});Input: string (path or URL), Buffer, Uint8Array, or URL
Individual Verification Methods
Run a single provider and get its result directly:
import {
verifyMetadata,
verifyC2PA,
verifySynthID,
verifyOpenAI,
verifyAdobe,
verifyGemini,
verifyStabilityAI,
} from "ai-image-detector";
// Metadata (EXIF / XMP / PNG chunks)
const metadata = await verifyMetadata("./image.png");
// C2PA Content Credentials
const c2pa = await verifyC2PA("./image.jpg");
// Google SynthID
const synthid = await verifySynthID("./image.jpg", {
apiKey: "your-google-cloud-api-key",
projectId: "your-project-id",
});
// OpenAI DALL-E
const openai = await verifyOpenAI("./image.png", {
apiKey: "sk-...",
});
// Adobe Firefly
const adobe = await verifyAdobe("./image.jpg", {
clientId: "your-adobe-client-id",
accessToken: "your-adobe-token",
});
// Google Gemini / Imagen
const gemini = await verifyGemini("./image.png", {
apiKey: "your-google-api-key",
projectId: "your-project-id",
});
// Stable Diffusion / Stability AI
const stability = await verifyStabilityAI("./image.png");Provider Coverage
| Provider | Metadata | C2PA | Watermark | API Verification |
|----------|----------|------|-----------|-----------------|
| Metadata | ✅ EXIF/XMP/PNG/IPTC | — | — | — |
| C2PA | — | ✅ JUMBF + Claims | — | ✅ optional c2pa-node |
| SynthID | ✅ XMP/EXIF | — | 🔜 when API released | 🔜 Google API |
| OpenAI | ✅ EXIF/XMP/PNG | ✅ DALL-E 3 C2PA | — | 🔜 when released |
| Adobe | ✅ EXIF/XMP | ✅ Firefly C2PA | — | ✅ Adobe I/O API |
| Gemini | ✅ EXIF/XMP/IPTC | ✅ C2PA actions | 🔜 SynthID co-proof | 🔜 Vertex AI API |
| Stability AI | ✅ EXIF | — | — | ✅ PNG param chunks |
TypeScript Interfaces
interface VerificationResult {
verified: boolean;
confidence: number; // 0 – 1
providers: string[];
checks: {
metadata?: CheckResult;
c2pa?: CheckResult;
synthid?: CheckResult;
openai?: CheckResult;
adobe?: CheckResult;
gemini?: CheckResult;
stabilityAI?: CheckResult;
[key: string]: CheckResult | undefined;
};
providerResults: ProviderResult[];
metadata?: Record<string, unknown>;
verifiedAt: string; // ISO-8601
}
interface ProviderResult {
provider: string;
verified: boolean;
confidence: number;
checks: Record<string, CheckResult>;
metadata?: Record<string, unknown>;
verifiedAt: string;
warnings?: string[];
error?: string;
}
interface CheckResult {
passed: boolean;
message: string;
confidence?: number;
severity?: "info" | "warning" | "error";
details?: Record<string, unknown>;
}Plugin System
Extend ai-image-detector with your own provider — no core modification needed.
import { registerProvider, verifyImage } from "ai-image-detector";
import type { ProvenanceProvider, ProviderResult, ImageInput } from "ai-image-detector";
class MidjourneyProvider implements ProvenanceProvider {
readonly name = "Midjourney";
async verify(image: ImageInput): Promise<ProviderResult> {
// Your verification logic here
const buffer = /* load image */;
const hasMjMeta = buffer.includes(Buffer.from("Midjourney"));
return {
provider: this.name,
verified: hasMjMeta,
confidence: hasMjMeta ? 0.9 : 0,
checks: {
midjourney_meta: {
passed: hasMjMeta,
message: hasMjMeta ? "Midjourney metadata found" : "No Midjourney metadata",
},
},
verifiedAt: new Date().toISOString(),
};
}
}
// Register once at startup
registerProvider(new MidjourneyProvider());
// Now included in verifyImage automatically
const result = await verifyImage("./image.png");What Each Provider Checks
Metadata Provider
Scans EXIF, XMP, IPTC, and PNG tEXt/iTXt chunks for AI generation evidence:
- EXIF
Softwarefield (e.g. "Stable Diffusion", "DALL-E", "Adobe Firefly") - XMP
xmp:CreatorToolnamespace - EXIF
UserComment/ImageDescriptionwith prompt-like content - PNG
parameters/workflow/prompttext chunks
C2PA Provider
Verifies C2PA Content Credentials (the Coalition for Content Provenance and Authenticity standard):
- JUMBF box detection in JPEG APP11 / PNG caBX / WebP
- C2PA label validation (
"c2pa"inside JUMBF superbox) - Claim signature block presence (
ES256,ES384, etc.) - AI generation action assertions (
c2pa.ai.generatedContent,com.adobe.firefly.generated) - XMP-based C2PA provenance reference
- Optional
c2pa-nodenative full validation (install separately)
SynthID Provider
Checks for Google SynthID evidence:
- SynthID XMP field detection
- Google AI EXIF software hints
- IPTC source field scanning
- Official Google Cloud API (when credentials provided)
OpenAI Provider
Checks for DALL-E provenance:
- EXIF
Software="DALL-E"/"OpenAI DALL-E 3" - OpenAI XMP namespace fields
- C2PA action
com.openai.generated(DALL-E 3 always includes C2PA) - PNG metadata chunks from the OpenAI API response
- Optional OpenAI provenance API
Adobe Provider
Checks for Adobe Firefly and Photoshop Generative Fill provenance:
- EXIF
Software="Adobe Firefly" - Adobe XMP namespaces (
photoshop:,xmpMM:,Iptc4xmpExt:) - C2PA action
com.adobe.firefly.generated contentcredentials.orgorigin marker- Optional Adobe I/O Content Authenticity API
Gemini Provider
Checks for Google Gemini / Imagen provenance:
- EXIF / binary Google AI software hints
- Google XMP namespace fields
- C2PA Google action assertions
- IPTC source field
- SynthID co-presence (expected for Gemini images)
- Optional Vertex AI API
Stability AI Provider
Checks for Stable Diffusion provenance (the richest metadata of any AI generator):
- PNG
parameterstEXt chunk (AUTOMATIC1111/InvokeAI/Fooocus format) - PNG
workflowtEXt chunk (ComfyUI JSON format) - EXIF Software field (many SD frontends write this)
- Parsed AUTOMATIC1111 parameter extraction (prompt, seed, model, steps, etc.)
- Stability AI XMP fields
Advanced Usage
Parallel vs Sequential
// Parallel (default) — fastest
const result = await verifyImage(image, { parallel: true });
// Sequential — useful for debugging
const result = await verifyImage(image, { parallel: false });Stream / Buffer
import { readFile } from "fs/promises";
const buffer = await readFile("./image.png");
const result = await verifyImage(buffer);From URL
const result = await verifyImage("https://example.com/photo.jpg");Custom Timeout
const result = await verifyImage(image, { timeout: 5_000 });Per-provider Options
const result = await verifyImage(image, {
providerOptions: {
SynthID: { apiKey: "gcloud-key", projectId: "my-project" },
Adobe: { clientId: "adobe-id", accessToken: "adobe-token" },
OpenAI: { apiKey: "sk-..." },
},
});Exit Code Integration (CI)
npx ai-image-detector image.png --providers openai,adobe || echo "No provenance found"
# Exit code 0 = verified, 1 = not verified / errorConfidence Scoring
| Score | Meaning | |-------|---------| | 0.90 – 1.00 | Strong evidence — cryptographic signature or authoritative API confirmation | | 0.75 – 0.89 | High confidence — multiple independent signals agree | | 0.50 – 0.74 | Moderate — one clear signal but no cryptographic proof | | 0.00 – 0.49 | Low — weak hints only or conflicting signals | | 0.00 | No provenance evidence found |
The final confidence in VerificationResult is the weighted mean of all successful providers' confidence scores.
License
MIT — Copyright © 2025 ai-image-detector contributors
