# AI Character Reference Sheet (`dami_studio/ai-character-reference-bank`) Actor

AI character reference sheet: describe a character and get a consistent set of reference images, portrait, three-quarter, full body, side and four expressions, in one art style. A reusable character-bible prompt keeps it recognisable. Runs on your own OpenAI key. $150.00 per 1,000 characters.

- **URL**: https://apify.com/dami_studio/ai-character-reference-bank.md
- **Developed by:** [Dami's Studio](https://apify.com/dami_studio) (community)
- **Categories:** AI, Videos, Social media
- **Features:** Limited permissions
- **Stats:** 5 total users, 0 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: 5.00 out of 5 stars

## Pricing

from $144.00 / 1,000 character sheets

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.
Since this Actor supports Apify Store discounts, the price gets lower the higher subscription plan you have.

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

**AI character reference sheet with a matching set of images**: portrait,
three-quarter, full body, side profile and four expressions, all in one art style. You also get a
`characterBible` string, a block of prompt text you paste into later prompts so the same face, hair
and outfit keep turning up.

Two things up front. It runs on your own OpenAI key, so the renders land on your OpenAI bill on top
of the charge here. And the consistency is written, not locked: there is no reference image behind
it, so a character stays recognisable rather than identical.

| | |
|---|---|
| **Input** | One or more character descriptions |
| **Output** | One image per view, and a row per character with the image links and the character bible |
| **Ceiling** | Eight views per character, and no cap on how many characters |
| **Account needed** | Your own OpenAI API key |
| **Price** | $150.00 per 1,000 characters, so $0.15 a character on the Free plan, a little less on paid plans. The free plan's $5 a month covers about 33. OpenAI bills your key separately |

### 🔍 What AI Character Reference Sheet does

You give it a character. It sets your description and your `style` line into a character bible,
then renders that bible once per view you asked for. The bible comes from a fixed template, not from
a model, so it is the same text every time for the same input.

Eight views exist: `portrait`, `threequarter`, `fullbody`, `side`, `happy`, `angry`, `sad` and
`surprised`. Ask for a name that is not on that list and it is dropped without complaint. Ask for
nothing but names that are not on it and you get `portrait` alone.

Characters run in order and views run in order inside them, so a run of five characters at five
views each is 25 images made one after another. Expect a wait.

`aspectRatio` sets the shape: `1:1` is 1024x1024, `9:16` is 1024x1536, `16:9` is 1536x1024.

### 📋 What data you get from each character

| What you get | Field |
|---|---|
| One image per view, saved in the run's key-value store, with a direct link | `references[].imageKey`, `references[].imageUrl` |
| The reusable prompt text that carries the look forward | `characterBible` |
| Which view each image is | `references[].view` |
| Why a view failed, when one did | `references[].error` |
| The name you gave, and the tidied version used in file names | `name`, `slug` |
| Your description, unchanged | `description` |

### ▶️ How to make a character reference sheet

1. Open [AI Character Reference Sheet](https://apify.com/dami_studio/ai-character-reference-bank)
   and click **Try for free**.
2. Paste your key into **OpenAI API key (BYO)**.
3. Write your character into **Characters**. Be specific about age, hair, clothing and colours: that
   sentence is doing all the work.
4. Tick the views you want in **Reference views**.
5. Click **Start**, then take the images from the run's **Storage** tab and copy `characterBible`
   out of the row.

Start it with no key and you get the free demo record in the key-value store instead.

### 💰 How much does it cost to make a character reference sheet?

**$0.15 per character** on the Free plan, less on paid plans. The number of views does not
change it: three views or eight, the character is one charge. On the free plan, the $5 Apify gives
you each month covers about 33 characters.

You pay per character that produced at least one image. The keyless demo and a character whose views
all failed are not charged. OpenAI bills your own key separately for each render, and that side does
scale with the number of views, so a long view list is the expensive choice on your bill rather
than on this one.

### 📥 What you give it

```json
{
  "characters": [
    { "name": "Milo", "description": "a small brave fox cub with a red scarf and bright green eyes, cartoon style" }
  ],
  "views": ["portrait", "threequarter", "fullbody", "happy", "angry"],
  "aspectRatio": "1:1",
  "quality": "high"
}
```

| Field | Default | What it is |
|---|---|---|
| `characters` | none | Plain strings, or objects with `name` and `description`. The form opens with a fox cub filled in as an example, which is a starting point rather than a default. |
| `views` | `portrait`, `threequarter`, `fullbody` | Which of the eight to render. The form suggests five, which is a prefill, not the default: leave the field alone in the API and you get three. |
| `style` | `consistent character design, clean studio background, highly detailed, soft even lighting` | The art direction folded into every prompt. Change this and the whole set changes together. |
| `aspectRatio` | `1:1` | `1:1`, `9:16` or `16:9`. |
| `quality` | `high` | `low`, `medium` or `high`. This moves your own OpenAI bill, not the charge here. |
| `openaiApiKey` | none | Your own OpenAI key. Marked secret. |
| `baseUrl` | none | Advanced. Any OpenAI-compatible host. Empty means `https://api.openai.com/v1`. |

Give each character a different `name`. The image keys are built from it, so two characters called
the same thing write to the same key and the second one overwrites the first.

Run it with a key but no usable character and the run stops with an error, because there is nothing
to draw.

### 📤 What you get back

One dataset row per character, with the images themselves in the run's key-value store under keys
like `milo-portrait-1786411663909.png`.

No run on record has rendered with a customer's key, so here is the real demo record a keyless run
wrote on 2 October 2026, notice cut short. Its `characterBible` is exactly what a real run returns
for this input. A delivered row has no `_demo` or `_notice`, and each entry in `references` carries
an `imageKey` and an `imageUrl` instead of `null`.

```json
{
  "_demo": true,
  "_notice": "SAMPLE OUTPUT ... Supply \"openaiApiKey\" to generate real reference images.",
  "ok": true,
  "name": "Milo",
  "slug": "milo",
  "description": "a small brave fox cub with a red scarf and bright green eyes, cartoon style",
  "characterBible": "Milo: a small brave fox cub with a red scarf and bright green eyes, cartoon style. Style: consistent character design, clean studio background, highly detailed, soft even lighting. Always render this exact character identically (same face, hair, clothing, colors) in every scene.",
  "references": [
    { "view": "portrait", "_demo": true, "imageKey": null },
    { "view": "threequarter", "_demo": true, "imageKey": null },
    { "view": "fullbody", "_demo": true, "imageKey": null },
    { "view": "happy", "_demo": true, "imageKey": null },
    { "view": "angry", "_demo": true, "imageKey": null }
  ]
}
```

| Field | How to read it |
|---|---|
| `characterBible` | The reusable prompt text. This is the part worth keeping. |
| `references` | One entry per view. A rendered view carries `view`, `imageKey` and `imageUrl`. A view that failed carries `view` and `error` instead. |
| `name` | What you called them, or `null` if you passed a plain string. |
| `slug` | The tidied name used in the file keys. Unnamed characters get `character-1`, `character-2`. |

### 🧾 Reading the output

A character is in the dataset when at least one of its views came back. Everything else goes to the
`SAMPLE_AND_NOTICES` record in the run's key-value store.

| Record | Where it lands | Billed |
|---|---|---|
| A character with one or more images | A dataset row | yes |
| The keyless demo | Key-value store, `SAMPLE_AND_NOTICES`, `_demo: true` | no |
| A character where every view failed | Key-value store, `SAMPLE_AND_NOTICES`, `ok: false` | no |
| The time limit: the run stops just before it, a character it cut short keeps the views it has, and the rest are not started. With no image made, the run is marked failed | Key-value store, `SAMPLE_AND_NOTICES`, `errorCode: TIME_LIMIT` | no |

Read `references` before you use a row, because **a character with one view out of five still
counts as one character and is charged as one.** The four that failed are sitting in that array with
their reason next to them, and `image_gen_failed_<status>` is the shape those messages take.

If every view of every character fails, the run still ends green with an empty dataset. Look in
`SAMPLE_AND_NOTICES` and at the run log, where each failed view is warned about by name.

The Overview table shows `name`, `slug`, `description`, `characterBible` and `references`. The
images are not previewed there, since `references` renders as raw JSON in a table cell. Open the
key-value store to actually look at them.

### 💡 What people use it for

- Keeping a cast straight across a comic or webtoon, where the same four people appear in every
  panel.
- Faceless video series with a recurring narrator or mascot.
- Game and animation pitches, where a character sheet is the deliverable.
- Building `characterBible` strings once and reusing them in other image tools for months.

From one character to a storyboard video, in three runs:

1. Run this on your lead character and copy `characterBible` from the row.
2. Paste it into **Character notes** on
   [AI Storyboard Generator](https://apify.com/dami_studio/ai-storyboard-generator), with your
   story in **Story / script**.
3. Give the scene `imageUrl` values to
   [Storyboard Video Generator](https://apify.com/dami_studio/storyboard-video-generator) as
   **Image URLs**.

### 🚧 What it does not do

- **No reference-image locking.** Consistency comes from the written bible, not from a locked face,
  so expect family resemblance rather than a clone.
- **No retries.** A view that fails once fails for good in that run, including a rate-limit refusal.
  Run it again.
- **Every file is saved as PNG**, with a PNG content type, whatever came back.
- **No editing, no upscaling, no posing.** It renders the eight views it knows and stops.
- **Partial sets bill in full.** One view out of five is still a character and still $0.15.
- **Same name, same file key.** Two characters with the same name overwrite each other's images.
- **No photos in.** It works from text only.
- It is not an official tool of any platform or company named on this page. Dami's Studio is independent and is not affiliated with or endorsed by any of them.

### 🧭 Which AI image actor do you need?

| If you want | Use |
|---|---|
| One character in a set of matching views | This one |
| A run of scene images that tell a story | [AI Storyboard Generator](https://apify.com/dami_studio/ai-storyboard-generator) |
| A single thumbnail built to be clicked | [AI Thumbnail Generator](https://apify.com/dami_studio/viral-thumbnail-generator) |
| A finished vertical video, script and voice included | [AI Faceless Video Generator](https://apify.com/dami_studio/ai-faceless-short-generator) |
| Images you already have turned into a video | [Storyboard Video Generator](https://apify.com/dami_studio/storyboard-video-generator) |

### ❓ Questions people ask

#### Do I need my own OpenAI key for character images?

Yes, for the renders. Without one you get the demo record.

#### Can I run several characters at once?

Yes. Put them all in `characters` and each becomes its own row and its own charge.

#### What do I actually do with the character bible?

Paste it into the prompt of whatever you draw with next. That is the string that carries the look
forward.

#### Why did one of my views come back empty?

Its reason is in that entry of `references`. Usually the key was refused, or the image model is not
available on the host you pointed at.

#### Can I call it from code or connect it to an AI assistant?

The [API tab](https://apify.com/dami_studio/ai-character-reference-bank/api/python) has code for Python, JavaScript
and the CLI. MCP clients like Claude and ChatGPT use
`https://mcp.apify.com/?tools=fetch-actor-details,dami_studio/ai-character-reference-bank`; coding assistants can load
[our skill file](https://api.apify.com/v2/key-value-stores/BTBHU3DdiuoF4JOsK/records/apify-ai-video-content-SKILL.md).
All three bill your Apify account at the same price, and OpenAI bills your key as usual.

### 🆘 If something breaks

Open the **Issues** tab on the actor page. Include the run ID and the `error` text from the
`references` entry that failed, since that message says what the image call actually answered.

# Actor input Schema

## `characters` (type: `array`):

Array of character descriptions, plain strings, or objects { name, description }.

## `views` (type: `array`):

Which views/expressions to render: portrait, threequarter, fullbody, side, happy, angry, sad, surprised.

## `style` (type: `string`):

Shared art style for the character set.

## `aspectRatio` (type: `string`):

Image shape.

## `quality` (type: `string`):

gpt-image-2.5-flare quality.

## `openaiApiKey` (type: `string`):

Your OpenAI key (gpt-image-2.5-flare). Kept private.

## `baseUrl` (type: `string`):

OpenAI-compatible base URL. Default https://api.openai.com/v1.

## Actor input object example

```json
{
  "characters": [
    {
      "name": "Milo",
      "description": "a small brave fox cub with a red scarf and bright green eyes, cartoon style"
    }
  ],
  "views": [
    "portrait",
    "threequarter",
    "fullbody",
    "happy",
    "angry"
  ],
  "style": "consistent character design, clean studio background, highly detailed, soft even lighting",
  "aspectRatio": "1:1",
  "quality": "high"
}
```

# Actor output Schema

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

Result rows / metadata are stored in the default dataset (one row per item).

## `files` (type: `string`):

Generated media/files (video, audio, images, captions) are stored in the default key-value store.

# 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 = {
    "characters": [
        {
            "name": "Milo",
            "description": "a small brave fox cub with a red scarf and bright green eyes, cartoon style"
        }
    ],
    "views": [
        "portrait",
        "threequarter",
        "fullbody",
        "happy",
        "angry"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("dami_studio/ai-character-reference-bank").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 = {
    "characters": [{
            "name": "Milo",
            "description": "a small brave fox cub with a red scarf and bright green eyes, cartoon style",
        }],
    "views": [
        "portrait",
        "threequarter",
        "fullbody",
        "happy",
        "angry",
    ],
}

# Run the Actor and wait for it to finish
run = client.actor("dami_studio/ai-character-reference-bank").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 '{
  "characters": [
    {
      "name": "Milo",
      "description": "a small brave fox cub with a red scarf and bright green eyes, cartoon style"
    }
  ],
  "views": [
    "portrait",
    "threequarter",
    "fullbody",
    "happy",
    "angry"
  ]
}' |
apify call dami_studio/ai-character-reference-bank --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,dami_studio/ai-character-reference-bank"
        }
    }
}
```

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/dxBbCpOHkUfLAZ5ir/builds/ntexPBpPTHFNg53dW/openapi.json
