# Stable Diffusion Prompt Extractor: A1111, ComfyUI, NovelAI (`chivalrous_skyline_vtd/sd-prompt-extractor`) Actor

Read the prompt, negative prompt, seed, sampler, model and LoRAs embedded in AI images from AUTOMATIC1111, Forge, ComfyUI, NovelAI and InvokeAI. Give image URLs, get structured JSON.

- **URL**: https://apify.com/chivalrous_skyline_vtd/sd-prompt-extractor.md
- **Developed by:** [HexaX](https://apify.com/chivalrous_skyline_vtd) (community)
- **Categories:** AI, Developer tools
- **Security:** Limited permissions
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

$1.50 / 1,000 image with metadata

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.

Learn more: https://docs.apify.com/actors/running/actors-in-store.md#pay-per-event

## What's an Apify Actor?

An Actor is a serverless cloud program that runs on the Apify platform. It has two run modes.
In Batch mode, an Actor accepts a well-defined JSON input, performs an action which can take anything from a few seconds to a few hours,
and optionally produces a well-defined JSON output, datasets with results, or files in key-value store.
In Standby mode, an Actor provides a web server which can be used as a website, API, or an MCP server.

Apify vocabulary and the platform model are defined once, in the agent quickstart at https://apify.com/agents.md.

## How to integrate an Actor?

If asked about integration, you help developers integrate Actors into their projects.
You adapt to their stack and deliver integrations that are safe, well-documented, and production-ready.

Do not guess an integration path. Every one of them is in the agent quickstart at https://apify.com/agents.md: the Apify MCP server, Agent Skills with the Apify CLI, the JavaScript and Python clients, the REST API, and the account-free path for an agent with no human to sign in. It also carries the rule on stating cost before the first paid run.

For examples already wired to this Actor's own input schema, see the [API](#api) section below.

Each client library has reference documentation the quickstart does not restate: [JavaScript/TypeScript](https://docs.apify.com/api/client/js/docs.md) (`npm install apify-client`) and [Python](https://docs.apify.com/api/client/python/docs.md) (`pip install apify-client`).

# README

## Stable Diffusion Prompt Extractor: A1111, ComfyUI, NovelAI

The Stable Diffusion prompt extractor for image URLs: get the **prompt, negative prompt, seed, sampler, steps, CFG, model and LoRAs** out of AI-generated images.
Give it a list of image URLs; it downloads each file and reads the generation metadata that the tools wrote into it. Output is structured JSON, so it works for one image or a whole gallery, from the Console or through the API.

### What you get

- Positive and negative prompt, seed, sampler, scheduler, steps, CFG, size, model, model hash and LoRAs, one row per image.
- The generating tool (`a1111`, `comfyui`, `novelai`, `invokeai`).
- Optional raw metadata for ComfyUI workflows and anything the parser does not map.

### Use cases

- **Gallery analysis**: collect the prompts and settings behind a set of public images.
- **Dataset captioning**: turn embedded prompts into captions for training data you own.
- **Prompt statistics**: count models, samplers, LoRAs and frequent prompt words across many images.
- **Metadata audit**: find which of your files still carry (or have lost) generation data.

### Quick start

Keep the example image URLs (small public test files with embedded metadata) and press Start, then replace them with your own.

| Tool | Where the metadata lives | Supported |
|---|---|---|
| AUTOMATIC1111 / Forge / SD.Next | PNG text chunk `parameters`, or EXIF `UserComment` in JPEG/WebP | ✅ |
| ComfyUI | PNG text chunks `prompt` (API graph) and `workflow` | ✅ (prompt, sampler settings, checkpoint, LoRA loaders, latent size) |
| NovelAI | PNG `Software` + `Comment` JSON | ✅ |
| InvokeAI | PNG `invokeai_metadata` JSON | ✅ |

Many sites strip metadata when they re-encode uploads. Those images come back as `no_metadata`, and **you are not charged for them**.

### Input

```json
{
  "imageUrls": [
    "https://raw.githubusercontent.com/d3x-at/sd-parsers/master/tests/resources/parsers/AUTOMATIC1111/automatic1111_cropped.png",
    "https://raw.githubusercontent.com/d3x-at/sd-parsers/master/tests/resources/parsers/NovelAI/novelai1_cropped.png",
    "https://raw.githubusercontent.com/d3x-at/sd-parsers/master/tests/resources/parsers/InvokeAI/invokeai_imeta1.png",
    "https://raw.githubusercontent.com/comfyanonymous/ComfyUI_examples/master/2_pass_txt2img/hiresfix_latent_workflow.png"
  ],
  "includeRawMetadata": false,
  "skipImagesWithoutMetadata": false,
  "maxImageSizeMb": 30,
  "maxConcurrency": 4
}
```

| Field | Default | Notes |
|---|---|---|
| `imageUrls` | (required) | Direct image links, up to 5,000 per run. Duplicates are removed. |
| `includeRawMetadata` | `false` | Adds `raw_metadata` with the original text chunks (ComfyUI workflows can be large). |
| `skipImagesWithoutMetadata` | `false` | Leave out rows for images without metadata. Errors are always reported. |
| `maxImageSizeMb` | `30` | Bigger files are skipped. 1–100. |
| `maxConcurrency` | `4` | Parallel downloads, 1–10. Lower it if a site rate-limits you. |

### Output

One dataset row per URL:

```json
{
  "url": "https://raw.githubusercontent.com/d3x-at/sd-parsers/master/tests/resources/parsers/AUTOMATIC1111/automatic1111_cropped.png",
  "status": "ok",
  "error": null,
  "image_format": "PNG",
  "generator": "a1111",
  "positive_prompt": "masterpiece, 1girl, <lora:animeStyle:0.8>, smile",
  "negative_prompt": "lowres, bad hands",
  "steps": 28,
  "sampler": "DPM++ 2M",
  "scheduler": "Karras",
  "cfg_scale": 6.5,
  "seed": 1234567890,
  "width": 832,
  "height": 1216,
  "model": "exampleModel_v10",
  "model_hash": "abc123",
  "denoise": 0.35,
  "loras": [{"name": "animeStyle", "weight": 0.8}]
}
```

`status` is one of:

- `ok`: metadata was found.
- `no_metadata`: the image was read but carries no generation data.
- `error`: the download or decoding failed; `error` says why.

### Pricing (pay per event)

| Event | Price | When |
|---|---|---|
| `image-with-metadata` | **$0.0015** ($1.50 per 1,000) | Each image whose generation metadata was found |
| Actor start | Apify default | Once per run |

Images without metadata and failed downloads are free. If you set a maximum charge for the run, the Actor stops once it is reached and says so in the status message.

### Limits and responsible use

- **robots.txt is respected.** Before downloading, the Actor reads each site's `robots.txt` and skips URLs it disallows. If `robots.txt` cannot be fetched because of a server error, the whole site is skipped. Only download images you have the right to access, and follow each site's terms of service.
- **No personal data.** Only the generation-metadata keys listed above are read. Camera EXIF, GPS coordinates, author/owner fields and any other chunks are never returned.
- Local and private network addresses (`localhost`, `10.x`, `192.168.x`, `169.254.x` …) are refused.
- Failed downloads are retried up to 3 times with backoff (timeouts, HTTP 408/425/429/5xx).
- ComfyUI graphs vary a lot. The Actor follows the sampler's `positive`/`negative` inputs back to text encoders, including primitive nodes and conditioning combiners. Exotic custom nodes may leave some fields `null`; use `includeRawMetadata` to get the full graph.

### FAQ

**Why do I get `no_metadata`?** Many sites (social networks, some galleries) strip metadata when they re-encode uploads. Use the original file. `no_metadata` rows are free.

**Can it read JPEG and WebP?** Yes, when the tool stored the settings in EXIF `UserComment` (AUTOMATIC1111 style). PNG text chunks are read for all four tools.

**Does it call any generation service?** No. It only downloads the files you point it to and reads the generation keys listed above.

### Run locally

```bash
python -m venv .venv && . .venv/bin/activate
pip install -r requirements.txt
python -m unittest discover -s tests -t .      # unit tests, no network

## Local run with the Apify CLI (`apify run`), or without it:
mkdir -p storage/key_value_stores/default
echo '{"imageUrls": ["https://example.com/a.png"]}' > storage/key_value_stores/default/INPUT.json
python -m src                                   # results in storage/datasets/default/
ACTOR_TEST_PAY_PER_EVENT=true python -m src     # also simulate pay-per-event charging locally
```

### Related actors

- [AI Crawler Checker & GEO / AEO Audit](https://apify.com/chivalrous_skyline_vtd/ai-search-readiness-audit): check a site for AI search readiness (llms.txt, AI bots, JSON-LD).
- [Video Frame Extractor](https://apify.com/chivalrous_skyline_vtd/video-frame-extractor): frames, scene changes and thumbnails from video file URLs.
- [Japanese to Romaji, Hiragana & Furigana Converter](https://apify.com/chivalrous_skyline_vtd/japanese-furigana-romaji): readings for Japanese text.
- [Japan Diet Parliament Debates & Speeches Search](https://apify.com/chivalrous_skyline_vtd/japan-diet-minutes): speeches from Japan's National Diet since 1947.

# Actor input Schema

## `imageUrls` (type: `array`):

Direct links to PNG, JPEG or WebP files (up to 5,000 per run). Only images you are allowed to download. Each site's robots.txt is checked before downloading.

## `includeRawMetadata` (type: `boolean`):

Also return the raw text chunks (A1111 'parameters', ComfyUI 'prompt' and 'workflow' JSON, NovelAI 'Comment'). ComfyUI workflows can be large.

## `skipImagesWithoutMetadata` (type: `boolean`):

Do not output a row for images that have no generation metadata (failed downloads are still reported).

## `maxImageSizeMb` (type: `integer`):

Images larger than this are skipped with an error.

## `maxConcurrency` (type: `integer`):

Lower this if a site rate-limits you.

## Actor input object example

```json
{
  "imageUrls": [
    "https://raw.githubusercontent.com/d3x-at/sd-parsers/master/tests/resources/parsers/AUTOMATIC1111/automatic1111_cropped.png",
    "https://raw.githubusercontent.com/d3x-at/sd-parsers/master/tests/resources/parsers/NovelAI/novelai1_cropped.png",
    "https://raw.githubusercontent.com/d3x-at/sd-parsers/master/tests/resources/parsers/InvokeAI/invokeai_imeta1.png",
    "https://raw.githubusercontent.com/comfyanonymous/ComfyUI_examples/master/2_pass_txt2img/hiresfix_latent_workflow.png"
  ],
  "includeRawMetadata": false,
  "skipImagesWithoutMetadata": false,
  "maxImageSizeMb": 30,
  "maxConcurrency": 4
}
```

# Actor output Schema

## `results` (type: `string`):

Results in the run's default dataset.

# API

You can run this Actor programmatically using our API. Below are code examples in JavaScript, Python, and CLI, as well as the OpenAPI specification and MCP server setup.

## JavaScript example

```javascript
import { ApifyClient } from 'apify-client';

// Initialize the ApifyClient with your Apify API token
// Replace the '<YOUR_API_TOKEN>' with your token
const client = new ApifyClient({
    token: '<YOUR_API_TOKEN>',
});

// Prepare Actor input
const input = {
    "imageUrls": [
        "https://raw.githubusercontent.com/d3x-at/sd-parsers/master/tests/resources/parsers/AUTOMATIC1111/automatic1111_cropped.png",
        "https://raw.githubusercontent.com/d3x-at/sd-parsers/master/tests/resources/parsers/NovelAI/novelai1_cropped.png",
        "https://raw.githubusercontent.com/d3x-at/sd-parsers/master/tests/resources/parsers/InvokeAI/invokeai_imeta1.png",
        "https://raw.githubusercontent.com/comfyanonymous/ComfyUI_examples/master/2_pass_txt2img/hiresfix_latent_workflow.png"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("chivalrous_skyline_vtd/sd-prompt-extractor").call(input);

// Fetch and print Actor results from the run's dataset (if any)
console.log('Results from dataset');
console.log(`💾 Check your data here: https://console.apify.com/storage/datasets/${run.defaultDatasetId}`);
const { items } = await client.dataset(run.defaultDatasetId).listItems();
items.forEach((item) => {
    console.dir(item);
});

// 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/js/docs

```

## Python example

```python
from apify_client import ApifyClient

# Initialize the ApifyClient with your Apify API token
# Replace '<YOUR_API_TOKEN>' with your token.
client = ApifyClient("<YOUR_API_TOKEN>")

# Prepare the Actor input
run_input = { "imageUrls": [
        "https://raw.githubusercontent.com/d3x-at/sd-parsers/master/tests/resources/parsers/AUTOMATIC1111/automatic1111_cropped.png",
        "https://raw.githubusercontent.com/d3x-at/sd-parsers/master/tests/resources/parsers/NovelAI/novelai1_cropped.png",
        "https://raw.githubusercontent.com/d3x-at/sd-parsers/master/tests/resources/parsers/InvokeAI/invokeai_imeta1.png",
        "https://raw.githubusercontent.com/comfyanonymous/ComfyUI_examples/master/2_pass_txt2img/hiresfix_latent_workflow.png",
    ] }

# Run the Actor and wait for it to finish
run = client.actor("chivalrous_skyline_vtd/sd-prompt-extractor").call(run_input=run_input)

# Fetch and print Actor results from the run's dataset (if there are any)
print(f"💾 Check your data here: https://console.apify.com/storage/datasets/{run.default_dataset_id}")
for item in client.dataset(run.default_dataset_id).iterate_items():
    print(item)

# 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/python/docs/quick-start

```

## CLI example

```bash
echo '{
  "imageUrls": [
    "https://raw.githubusercontent.com/d3x-at/sd-parsers/master/tests/resources/parsers/AUTOMATIC1111/automatic1111_cropped.png",
    "https://raw.githubusercontent.com/d3x-at/sd-parsers/master/tests/resources/parsers/NovelAI/novelai1_cropped.png",
    "https://raw.githubusercontent.com/d3x-at/sd-parsers/master/tests/resources/parsers/InvokeAI/invokeai_imeta1.png",
    "https://raw.githubusercontent.com/comfyanonymous/ComfyUI_examples/master/2_pass_txt2img/hiresfix_latent_workflow.png"
  ]
}' |
apify call chivalrous_skyline_vtd/sd-prompt-extractor --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,chivalrous_skyline_vtd/sd-prompt-extractor"
        }
    }
}
```

The hosted server signs you in with OAuth on first connect, so no API token belongs in this config. Clients without OAuth support can send an `Authorization: Bearer <APIFY_API_TOKEN>` header instead, using a token from API & Integrations in Apify Console (https://console.apify.com/settings/integrations).

## OpenAPI specification

Download the OpenAPI definition: https://api.apify.com/v2/actors/RLhSWEeSymGvqJYYP/builds/b0nAhIpmrwvrDyKoe/openapi.json
