Actor definition
An actor folder holds your code, a Dockerfile and an .actor/ folder that describes the actor. lantfly push reads .actor/actor.json to create or update the actor and its version.
my-actor/
.actor/
actor.json # the actor definition
input_schema.json # input form and validation
dataset_schema.json # result views in the Console (optional)
output_schema.json # links shown as the run's outputs (optional)
Dockerfile
.dockerignore
src/main.js # or main.py
package.json # or requirements.txt
actor.json
{
"actorSpecification": 1,
"name": "my-actor",
"title": "My Actor",
"description": "My Actor actor",
"version": "0.1",
"buildTag": "latest",
"input": "./input_schema.json",
"storages": { "dataset": "./dataset_schema.json" },
"dockerfile": "../Dockerfile"
}
| Field | Required | Meaning |
|---|---|---|
actorSpecification | Always 1. | |
name | yes | The actor's name in your account: lowercase letters, digits and dashes (^[a-z0-9][a-z0-9-]*$). Its id in the API is <username>~<name>. |
title | Display name. Default: name. | |
description | One-line description shown on the actor's page and in the Store. | |
version | Version that push creates or updates, as major.minor (for example 0.1). Default 0.1. --version overrides it. | |
input | The input schema: a path relative to .actor/, or the schema itself. Without it, push looks for .actor/input_schema.json, then INPUT_SCHEMA.json in the folder. | |
storages.dataset | The dataset schema: a path relative to .actor/, or the schema itself. | |
output | The output schema: a path relative to .actor/, or the schema itself. | |
dockerfile | The Dockerfile, relative to .actor/ (so ../Dockerfile is the folder's root). Default: Dockerfile in the actor folder. | |
image | The image to run, without tag. Default: the actor's current image, or lantfly/<namespace>/<name>. | |
buildTag | Written by lantfly init; not used by push. |
What push sends where:
- To the actor:
name,title,description,imageand the input schema. - To the version: the input schema, the dataset schema and the output schema. A new version is created with image tag
latestand made the default.
The README, categories, example input, default run options and pricing are set on the actor in the Console or with PATCH /api/v3/actors/{actor} (see the API reference).
Dockerfile
The image is a normal Docker image. Lantfly starts it with its default command, as user 1000:1000, with the run's environment variables. Follow these rules:
- Run as a non-root user with uid 1000 (
USER nodein the official Node.js images, orUSER 1000:1000). - Use an init process such as
tinias the entrypoint, so SIGTERM reaches your program and the SDK can flush data before the run stops. - Write temporary files to
/tmp: the working directory may not be writable. The SDK points Crawlee's local storage to/tmp/crawlee. - Keep
node_modules,storageand.gitout of the build context with.dockerignore.
The Dockerfile from lantfly init:
FROM node:22-bookworm-slim
ENV NODE_ENV=production
WORKDIR /app
COPY package*.json ./
RUN npm install --omit=dev --no-audit --no-fund
COPY . ./
USER node
CMD ["npm", "start", "--silent"]
A production image for a Crawlee actor, with tini, a fixed time zone and UTF-8:
FROM node:22-bookworm-slim
ENV NODE_ENV=production LANG=C.UTF-8 LC_ALL=C.UTF-8 CRAWLEE_STORAGE_DIR=/tmp/crawlee
RUN apt-get update \
&& apt-get install -y --no-install-recommends tini ca-certificates procps \
&& rm -rf /var/lib/apt/lists/* \
&& mkdir -p /tmp/crawlee && chown node:node /tmp/crawlee
WORKDIR /app
COPY package*.json ./
RUN npm ci --omit=dev --no-audit --no-fund
COPY . ./
USER node
ENTRYPOINT ["tini", "--"]
CMD ["node", "src/main.js"]
Crawlee's browser pool reads memory with ps. Slim Debian images have none, so install procps for browser crawlers.
Input schema
.actor/input_schema.json describes the input. The Console builds the run form from it, the platform fills in default values, and the API refuses inputs that do not match it (422). See Input schema.
{
"title": "My Actor input",
"type": "object",
"schemaVersion": 1,
"properties": {
"message": { "title": "Message", "type": "string", "description": "Text stored in every item.", "editor": "textfield", "default": "Hello from Lantfly" },
"count": { "title": "Count", "type": "integer", "description": "How many items to push.", "minimum": 1, "maximum": 1000, "default": 3 }
},
"required": []
}
Dataset schema
.actor/dataset_schema.json tells the Console how to show the results. Each view picks and orders fields and says how to display them.
{
"actorSpecification": 1,
"fields": {
"type": "object",
"properties": {
"index": { "type": "integer" },
"message": { "type": "string" },
"at": { "type": "string" }
}
},
"views": {
"overview": {
"title": "Overview",
"transformation": { "fields": ["index", "message", "at"] },
"display": {
"component": "table",
"properties": {
"index": { "label": "#", "format": "number" },
"message": { "label": "Message", "format": "text" },
"at": { "label": "At", "format": "date" }
}
}
}
}
}
| Key | Meaning |
|---|---|
views.<name>.title | Name of the view in the Console. |
views.<name>.transformation.fields | Fields of the view, in order (required). |
views.<name>.transformation.unwind, flatten, omit, desc | The same as the dataset items parameters. |
views.<name>.display.component | table. |
views.<name>.display.properties.<field> | label and format: text, number, date, link, image, boolean, array or object. |
The schema is checked when you save the version. A run's views are returned by GET /api/v3/runs/{run}/views, each with the query (dataset item parameters) that applies it. You can also ask for a view directly:
curl "https://lantfly.com/api/v3/datasets/<datasetId>/items?view=overview" \
-H "Authorization: Bearer $LANTFLY_TOKEN"
Parameters you pass explicitly win over the view. An unknown view answers 400 invalid_parameter.
Output schema
.actor/output_schema.json lists links to show as the run's outputs. Each property has a title and a template with placeholders that are filled with /api/v3 URLs of the run:
{
"actorSpecification": 1,
"properties": {
"results": {
"title": "Results",
"template": "{{links.apiDefaultDatasetUrl}}/items?view=overview"
},
"summary": {
"title": "Summary",
"template": "{{links.apiDefaultKeyValueStoreUrl}}/records/OUTPUT"
}
}
}
Placeholders include {{links.apiDefaultDatasetUrl}}, {{links.apiDefaultKeyValueStoreUrl}}, {{links.apiRunUrl}} and {{run.id}}. The filled links come back in the outputs of GET /api/v3/runs/{run}/views.
What the actor writes
| Where | What |
|---|---|
| Default dataset | One item per result (Actor.pushData). Error rows from the SDK have an error field. |
Default key-value store, INPUT | The input of the run (written by the platform). |
Default key-value store, OUTPUT | A summary of the run. The SDKs write it at the end of Actor.main with the run status and the outcome of each input. |
| Default key-value store, other keys | Anything else: screenshots, files, state. |
| Status message | A short line shown on the run (Actor.setStatusMessage). |