# Split into Layers

> Split one image into a base picture and separate layers, each element on its own transparent PNG, with its name, position box and stacking order.

Source: https://nodaro.ai/docs/nodes/image/split-into-layers

The **Split into Layers** node pulls one picture apart into a base picture and separate layers. Each element, such as a person, an animal, a product, a line of text or a logo, comes back as its own transparent PNG. The node also returns layer data that says what each layer is, where it sits and how the layers stack.

Edit, animate or replace the layers one by one, then put them back together. Leave **What to separate** empty and the node finds the main elements itself, or describe the elements you want.

- Found in: Image › Edit & Retouch
- API type: `split-into-layers`

## When to use it
- Edit one element of a picture, such as a product or a headline, without touching the rest.
- Animate each element on its own: connect the layers to [Generate Video](https://nodaro.ai/docs/nodes/video/generate-video).
- Upscale every element separately with [Upscale Image](https://nodaro.ai/docs/nodes/image/upscale-image).
- Recompose a picture: move, resize or swap elements, then place them back on the base picture.
- Get every element as a transparent PNG, ready for a design tool.

## Quick start
### Add the node

Press Tab on the canvas and choose **Image › Edit & Retouch › Split into Layers**.

### Connect the image

Connect an image node, such as [Upload Image](https://nodaro.ai/docs/nodes/image/upload-image) or [Generate Image](https://nodaro.ai/docs/nodes/image/generate-image), to the **Image** input. You can also upload a picture on the node.

### Choose the settings

Open the settings panel. Set **Max layers** and **Size**. To choose the elements yourself, describe them in **What to separate**.

### Run it

Click **Run** on the node. A run usually takes under a minute. The node shows the base picture and a strip of the layers, each with its name.

Workflow: A poster is split into layers, and an Each connection upscales every layer on its own.

- Upload Image → Split into Layers (image)
- Split into Layers → Upscale Image (layers)

## Inputs
| Input | Accepts | What it does |
| --- | --- | --- |
| **Image** | Image nodes, such as Upload Image, Generate Image and Modify Image, or a Character, Object or Location | The picture to split: JPEG, PNG or WebP. A larger file, or another format such as HEIC or AVIF, is converted first. A connected Character, Object or Location is used as the image. Required. |

## Outputs
| Output | What it carries |
| --- | --- |
| **Base** | The base picture, an opaque PNG. |
| **Layers** | A list of every layer, from bottom to top: transparent PNGs, each cut out to its element. |
| **Layer data** | One entry per layer, in the same order as **Layers**. |

**Layers** is a list. A connection from it in **Each** mode, the default, runs the next node once per layer. For example, connect it to Upscale Image to upscale every layer, or to Generate Video to animate each one. Set the connection to **Bundle** to hand every layer at once to a node that takes several images, such as [Image Collage](https://nodaro.ai/docs/nodes/image/image-collage) or the references of Generate Image. See [Lists and batching](https://nodaro.ai/docs/concepts/lists-and-batching).

The base picture and every layer are also filed in your Library. Each layer is filed under its name.

### Layer data

The **Layer data** output looks like this:

```json
[
{
"name": "Arctic fox",
"description": "The full body of the standing white arctic fox, with no background.",
"zIndex": 1,
"width": 1108,
"height": 946,
"box": { "x1": 228, "y1": 482, "x2": 897, "y2": 1070 },
"boxNormalized": { "x1": 223, "y1": 314, "x2": 875, "y2": 696 },
"url": "https://…/layer.png",
"baseUrl": "https://…/base.png"
}
]
```

| Field | What it means |
| --- | --- |
| `zIndex` | The stacking order. `1` sits on the base picture, and a higher number is drawn above it. |
| `box` | Where the layer sits on the base picture, in the base picture's pixels. `x1` and `y1` are the top-left corner, and `x2` and `y2` the bottom-right corner. |
| `boxNormalized` | The same box on a scale of 0 to 1000 of the base picture's width and height. |
| `width`, `height` | The pixels of the layer file itself. A layer is not cut at the base picture's scale. It is cropped to its element and saved at about the pixel budget of the **Size** setting (about one megapixel at 1K), in the element's own shape. To put a layer back in place, scale it to its `box`. |
| `name`, `description` | What the element is. A layer may come without them. |
| `url` | The layer's file, the same as its entry in **Layers**. |
| `baseUrl` | The base picture the layer was cut from, the same as **Base**. |

### Several pictures in one run

Connect a list of pictures to **Image**, such as a [List](https://nodaro.ai/docs/nodes/automate/list) of image links or a node that makes several images on an **Each** connection. The node then runs once per picture. Each run's result is its own take, with that picture's base, layers and layer data.

- **Base** lists one base picture for every picture that produced a result, in the order the pictures came in. A picture whose run failed has no base, so it is left out of the list.
- **Layers** hands on every picture's layers, picture by picture. An **Each** connection runs the next node once per layer of every picture: the first picture's layers, then the second picture's, and so on. A **Bundle** connection hands them all over at once, a **Selected** connection reads the first one, and an **Item** connection picks one from the whole list.
- **Layer data** lines up with those layers one for one. Each entry also carries `row`, the number of the input picture it came from, counting from 0. A picture with no layers adds nothing to **Layers** or **Layer data**, and neither does a picture whose run failed. Each picture keeps its number, so `row` can skip a number.

To pair a layer with its base picture, use its `baseUrl`, not its `row`. **Base** lists only the pictures that produced a result. Once a picture fails, a later picture's `row` no longer matches its place in **Base**. In the example below, the second picture failed. The owl's base picture is the second item of **Base**, while its `row` is 2.

```json
[
{ "name": "Fox", "zIndex": 1, "url": "https://…/fox.png", "baseUrl": "https://…/base-1.png", "row": 0 },
{ "name": "Owl", "zIndex": 1, "url": "https://…/owl.png", "baseUrl": "https://…/base-3.png", "row": 2 }
]
```

A run on one picture gives layer data without `row`, as in the first example. The node shows the layers of the take you are looking at. Choose another take to see that picture's layers. Connections from **Layers** and **Layer data** keep handing on every picture's layers, whichever take you choose. In the same way, an **Each** connection from **Base** keeps listing every picture's base picture. Before the first run, the run estimate counts an **Each** connection from **Layers** at **Max layers** for every picture.

## Settings
| Setting | What it does |
| --- | --- |
| **Max layers** | The most layers a run makes, from 1 to 99. The default is 9. The base picture comes on top of them. A picture with more elements than this gets fewer, larger layers, because elements are grouped, never dropped. |
| **Size** | The pixel budget of each image: `1K`, the default, `1.5K` or `2K`. **Auto** uses the picture's own size, between 1K and 2K. |
| **What to separate** | Optional, up to 2,000 characters. Describe in plain words which elements to split out. Leave it empty and the node finds the main elements itself. |

In **What to separate**, you can mark where an element is with `<bbox>x1 y1 x2 y2</bbox>`. The numbers are the corners on a scale of 0 to 1000 of the picture. For example:

```text
Separate the title <bbox>179 58 809 197</bbox> and the parrot <bbox>330 274 641 991</bbox>
```

### In a published app

An [app](https://nodaro.ai/docs/concepts/apps) built on a workflow with this node can let its users set **Max layers**, with a slider from 1 to 20, and **Size**, one of **Auto**, `1K`, `1.5K` or `2K`. The app's slider and any override of a workflow run are held to those values. Anything else is refused before the run starts.

An app sends only the values its user changed. A run that leaves **Max layers** untouched keeps the value the creator saved on the node, up to 99 layers, and is held for that value. For example, 50 layers saved on the node hold for 51 images. With the slider at its top, 20 layers at `2K` hold 369 credits.

## Credits
A run is **held** for the most images it may return: its **Max layers** plus the base picture. It is **charged** only for the images it really returns: the base picture and each layer. The sizes `1K` and `1.5K` cost the same, and `2K` and **Auto** cost more. The **Run** button shows the hold for the settings you chose.

| Example | Held | Charged |
| --- | --- | --- |
| The default: 9 layers at 1K | 104 | — |
| 3 layers returned at 1K (4 images) | | 44 |
| 3 layers returned at 2K or **Auto** (4 images) | | 74 |
| **Max layers** 5 at 1K | 64 | — |
| No element found: the base picture alone at 1K | | 15 |

- **No element found.** The run completes with the base picture alone and is charged for that one image.
- **A layer that cannot be saved.** If a layer still cannot be saved after a few tries, the run completes without it and is charged only for the images it saved. The node says how many layers could not be saved, for example "2 of 9 layers could not be saved".
- **A failed run is refunded.** This includes a run whose base picture cannot be saved.

Self-hosted Community and Business editions use no credits.

## Tips
- **Recompose in order.** To rebuild a picture, place each layer on the base picture at its `box`, in `zIndex` order.
- **Choose how much to group.** A lower **Max layers** groups elements together, such as a whole headline in one layer. A higher value keeps them apart.
- **Name the elements you need.** When the main elements are not the ones you want, describe them in **What to separate**, for example "the logo and the price tag".

## Troubleshooting
| Problem | What to do |
| --- | --- |
| The run returned only the base picture | The node found no element. Describe the elements you want in **What to separate**, or mark them with a `<bbox>`. |
| Two elements came out in one layer | The picture has more elements than **Max layers**. Raise **Max layers**. |
| A layer does not line up with the base picture | A layer file is not at the base picture's scale. Scale it to its `box` from the layer data before you place it. |
| The node says some layers could not be saved | The run completed without those layers and charged only for the images it saved. Run the node again to get them. |

## From the API
`POST /v1/split-into-layers` with `{ imageUrl, maxLayers?, size?, prompt?, sessionId?, origin? }` queues a job and answers with its `jobId`. A malformed request answers `400 validation_error` before any credits are held. `sessionId` files the job in one of your sessions, and `origin` tags it with your app's slug. An `Idempotency-Key` header makes a retry answer the job the first request started (`{ jobId, deduped: true }`) instead of starting a second one.

The finished job's `output_data.imageUrl` is the base picture and `output_data.layers` lists the layer files in order. `output_data.layerData` is the layer data above. `output_data.layerCount` is the number of layers saved, and `output_data.layersNotSaved` the number that could not be saved (`0` when every layer was saved).

To get the hold before a run, send `{ "type": "split-into-layers", "params": { … } }` to `POST /v1/quote`, with the same body. Nothing starts. The answer's `identifier` is the price it holds (`split-into-layers:<1k|2k>:<images>`), and `reserve` is the credits held: 64 for **Max layers** 5 at 1K, and 104 for the default. In the SDK, call `client.nodes.quote("split-into-layers", body)`. When you cannot run the node, the quote is refused like the run, with `403 node_not_available`.

The SDK method is `client.media.splitIntoLayers`, the MCP tool is `split_into_layers`, and the CLI command is `nodaro media split-layers`. See [Run a single node](https://nodaro.ai/docs/developers/api/nodes), [Jobs](https://nodaro.ai/docs/developers/api/jobs), [Media and uploads in the SDK](https://nodaro.ai/docs/developers/sdk/media-and-uploads) and the [MCP tools](https://nodaro.ai/docs/mcp/tools).

## Frequently asked questions

### What does Split into Layers return?

A base picture, which is the scene behind the elements, and one transparent PNG layer for each element, such as a person, a product, a line of text or a logo. It also returns layer data with each layer's name, position box and stacking order.

### Do I need to write a prompt?

No. Leave What to separate empty and the node finds the main elements itself. Describe the elements you want only when the main ones are not the ones you need.

### How many layers can one run make?

Up to the Max layers setting, from 1 to 99, with 9 as the default. A picture with more elements gets fewer, larger layers, because elements are grouped, never dropped.

### How much does Split into Layers cost?

A run is held for its Max layers plus the base, and charged only for the images it returns. The default, 9 layers at 1K, holds 104 credits. A run that returns 3 layers at 1K is charged 44 credits.

### How do I put the layers back together?

Place each layer on the base picture at its box, in stacking order from the lowest zIndex to the highest. A layer file is cropped to its element, so scale it to its box first.
