Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,13 @@
title: Actor web server schema
sidebar_label: Web server schema
sidebar_position: 7
description: Attach an OpenAPI specification to your Actor to enable the interactive Endpoints tab in Apify Console and Apify Store, where you can browse and test endpoints.
description: Attach an OpenAPI specification to your Actor to enable the interactive Server tab in Apify Console and Apify Store, where you can browse and test endpoints.
slug: /actors/development/actor-definition/web-server-schema
---

The `webServerSchema` field in `.actor/actor.json` attaches an [OpenAPI 3.x](https://spec.openapis.org/oas/v3.0.3) specification to your Actor. You can define the schema for any Actor that exposes an HTTP server. When you enable [standby mode](/actors/development/programming-interface/standby), Apify Console and Apify Store render an interactive **Endpoints** tab on the Actor's detail page. From there you can browse endpoints, inspect request and response schemas, and send requests directly from the browser.
The `webServerSchema` field in `.actor/actor.json` attaches an [OpenAPI 3.x](https://spec.openapis.org/oas/v3.0.3) specification to your Actor. You can define the schema for any Actor that exposes an HTTP server. When you enable [standby mode](/actors/development/programming-interface/standby), Apify Console and Apify Store render an interactive **Server** tab on the Actor's detail page. From there you can browse endpoints, inspect request and response schemas, and send requests directly from the browser.

![Apify Console showing the Endpoints tab rendered from the Actor's OpenAPI spec](../images/console-standby-openapi-swagger.png)
![Apify Console showing the Server tab rendered from the Actor's OpenAPI spec](../images/console-standby-openapi-swagger.png)

## Define the web server schema

Expand Down Expand Up @@ -94,7 +94,7 @@ The build process validates `webServerSchema`, similar to other Actor schemas li

The platform doesn't enforce the schema at runtime. Unlike input schema, the web server schema only documents your Actor's interface. The platform forwards incoming requests to your server without validating them or your server's responses against the schema. Your server must validate requests itself.

Once deployed, the **Endpoints** tab appears automatically on the Actor's detail page when you enable [standby mode](/actors/development/programming-interface/standby). It renders your spec with [Swagger UI](https://swagger.io/tools/swagger-ui/) and handles authentication automatically - Actor users can send requests without configuring API tokens.
Once deployed, the **Server** tab appears automatically on the Actor's detail page when you enable [standby mode](/actors/development/programming-interface/standby). It renders your spec with [Swagger UI](https://swagger.io/tools/swagger-ui/) and handles authentication automatically - Actor users can send requests without configuring API tokens.

:::note Servers field is overwritten

Expand All @@ -106,6 +106,6 @@ Your `servers` array is replaced with the Actor's standby URL at display time. C

| Field | Description |
| --- | --- |
| `usesStandbyMode` | Must be `true` for the **Endpoints** tab to appear. See [standby mode](/actors/development/programming-interface/standby). |
| `webServerSchema` | The OpenAPI spec that powers the **Endpoints** tab. Defined in [`.actor/actor.json`](/actors/development/actor-definition/actor-json) as an inline object or a path to a JSON file. |
| `usesStandbyMode` | Must be `true` for the **Server** tab to appear. See [standby mode](/actors/development/programming-interface/standby). |
| `webServerSchema` | The OpenAPI spec that powers the **Server** tab. Defined in [`.actor/actor.json`](/actors/development/actor-definition/actor-json) as an inline object or a path to a JSON file. |
| `webServerMcpPath` | The HTTP path where the Actor exposes its MCP server. The Actor's MCP endpoint is the Standby URL followed by this path. See [`.actor/actor.json`](/actors/development/actor-definition/actor-json). |
Original file line number Diff line number Diff line change
Expand Up @@ -6,33 +6,49 @@ slug: /actors/development/programming-interface/standby
sidebar_position: 9
---

Traditional Actors are designed to run a single task and then stop. They're mostly intended for batch jobs, such as when you need to perform a large scrape or data processing task.
However, in some applications, waiting for an Actor to start is not an option. Actor Standby mode solves this problem by letting you have the Actor ready
in the background, waiting for the incoming HTTP requests. In a sense, the Actor behaves like a real-time web server or standard API server.

## Developing Actors using Standby mode

import Tabs from '@theme/Tabs';
import TabItem from '@theme/TabItem';

The best way to start developing Standby Actors is to use the predefined templates in the [Console UI](https://console.apify.com/actors/templates) or in [CLI](https://docs.apify.com/cli/) via `apify create`. The templates contain minimal code to get you up to speed for development in JavaScript, TypeScript or Python. Standby mode will automatically be enabled with default settings.
While a traditional Actor runs a single job and stops, an Actor in Standby mode runs a persistent HTTP server and responds to incoming requests in real time. For the user-facing overview of Standby mode, including endpoints, authentication, scaling, configuration, and billing, see [Actor Standby mode](../../running/actor_standby.md).

## Enable Standby mode

You can enable Standby mode from a template, in Apify Console, or in the Actor's source code.

### Start from a template

The easiest way to start is a Standby template, in [Apify Console](https://console.apify.com/actors/templates) or with `apify create` in the [Apify CLI](https://docs.apify.com/cli/). The templates contain minimal JavaScript, TypeScript, or Python code, and Standby mode is enabled with default settings.

### Enable Standby in Apify Console

To enable or change Standby mode for an existing Actor, open the **Settings** tab of the Actor and find the Actor Standby settings.

If you already have an existing Actor, or you just want to tweak the configuration of Standby mode, you can head to the Settings tab of your Actor, where the Actor Standby settings are located.
![Standby for creators](./images/standby-creators.png)
![Standby settings in the Actor's Settings tab](./images/standby-creators.png)

You can also enable Standby mode from the Actor's source code by setting the [`usesStandbyMode`](../actor_definition/actor_json.md) property to `true` in the `.actor/actor.json` file. When you push the Actor with the [Apify CLI](https://docs.apify.com/cli/), the setting syncs to the platform.
To enforce the same Standby configuration for all users of your Actor, enable **Prevent users from overriding standby parameters** in the same settings. Users then can't override it by creating a task.

Actors using Standby mode must run a HTTP server listening on a specific port. The user requests will then be proxied to the HTTP server. You can use any of the existing [HTTP request methods](https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods) like GET, POST, PUT, DELETE, etc. You can pass the input via [HTTP request query string](https://en.wikipedia.org/wiki/Query_string) or via [HTTP request body](https://developer.mozilla.org/en-US/docs/Web/HTTP/Messages#body).
### Enable Standby in the source code

Sometimes, you want the HTTP server to listen on a specific port and cannot change it yourself. You can use `ACTOR_WEB_SERVER_PORT` environment variable to override the port so that Actor Standby will work with your code.
You can also enable Standby mode by setting the [`usesStandbyMode`](../actor_definition/actor_json.md) property to `true` in the `.actor/actor.json` file. When you push the Actor with the [Apify CLI](https://docs.apify.com/cli/), the setting syncs to the platform.

You can get the port using the Actor configuration available in Apify SDK.
See example below with a simple Actor using Standby mode.
## Run an HTTP server

A Standby Actor must run an HTTP server that listens on a specific port. The platform proxies user requests to that server. Requests can use any [HTTP request method](https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods), such as GET, POST, PUT, or DELETE, and pass input in the [query string](https://en.wikipedia.org/wiki/Query_string) or the [request body](https://developer.mozilla.org/en-US/docs/Web/HTTP/Messages#body).

### Get the port

The server must listen on the port defined by the `ACTOR_WEB_SERVER_PORT` environment variable. If you use the Apify SDK, read the port from the Actor configuration instead: the option is named `containerPort` in JavaScript and `web_server_port` in Python.

If your server must listen on a specific port that you can't change in code, define `ACTOR_WEB_SERVER_PORT` as a custom [environment variable](./environment_variables.md) of the Actor, with that port as the value. The platform then proxies the requests to your port.

### Example server

The example below is a minimal Standby Actor.

<Tabs groupId="main">
<TabItem value="JavaScript" label="JavaScript">

```js
```javascript
import http from 'http';
import { Actor } from 'apify';

Expand Down Expand Up @@ -68,25 +84,30 @@ async def main() -> None:
</TabItem>
</Tabs>

Describe your Actor's endpoints, their parameters, and responses with a [web server schema](../actor_definition/web_server_schema/index.md) defined in the [`.actor/actor.json`](../actor_definition/actor_json.md) file. Based on that definition, Apify Console renders an interactive **Endpoints** tab on the Actor's detail page, where users can browse the endpoints and send requests directly from the browser. Describe the endpoints in your Actor's [README](../../publishing/publish/actor-readme.mdx) as well, because that's what users see in Apify Store before they ever open the Actor's detail page.
## Describe your endpoints

Describe your Actor's endpoints, their parameters, and responses with a [web server schema](../actor_definition/web_server_schema/index.md) defined in the [`.actor/actor.json`](../actor_definition/actor_json.md) file. Based on that definition, Apify Console renders an interactive **Server** tab on the Actor's detail page, where users can browse the endpoints and send requests directly from the browser. Describe the endpoints in your Actor's [README](../../publishing/publish/actor-readme.mdx) as well, because users see the README in Apify Store before they open the Actor's detail page.

## Run lifecycle

The platform starts and stops Standby runs based on the incoming request load. It stops a run that receives no requests within the idle timeout and starts a new run when requests arrive again. Don't keep data only in the run's memory. Persist anything you need to a [dataset or key-value store](../../../storage/index.md). For details, see [how Standby scaling works](../../running/actor_standby.md#automatic-scaling), [how to customize the Standby configuration](../../running/actor_standby.md#standby-configuration), and [the timeouts and rate limits](../../running/actor_standby.md#limits-and-scaling) that apply to incoming requests.

### Readiness probe

Before Actor standby runs are ready to serve requests, the Apify platform checks the web server's readiness using a readiness probe.
The platform sends a GET request to the path `/` with a header `x-apify-container-server-readiness-probe`. If the header is present in the request, you can perform an early return with a simple response to prevent wasting resources.
Before a Standby run serves requests, the platform checks that the web server is ready. It sends a GET request to the path `/` with the `x-apify-container-server-readiness-probe` header. When a request carries this header, you can return a simple response early to avoid wasting resources.

:::note Return a response
:::caution Return a response

You must return a response; otherwise, the Actor run will never be marked as ready and won't process requests.
Always return a response. Otherwise, the platform never marks the run as ready, and it won't process requests.

:::

See example code below that distinguishes between "normal" and "readiness probe" requests.
The example below tells normal requests from readiness probes.

<Tabs groupId="main">
<TabItem value="JavaScript" label="JavaScript">

```js
```javascript
import http from 'http';
import { Actor } from 'apify';

Expand Down Expand Up @@ -133,16 +154,18 @@ async def main() -> None:
</TabItem>
</Tabs>

## Determining an Actor is started in Standby
### Run termination

A run ends when its process exits, when it stays idle for longer than the idle timeout, or when the platform replaces it. During a worker migration, the platform doesn't move the run to another machine. Instead, it starts a replacement run, waits until that run is ready, then stops sending requests to the old run and aborts it. Apart from the [readiness probe](#readiness-probe), the platform doesn't check your server's health while the run is alive. A server that stays up but stops responding keeps receiving requests, so on an unrecoverable error, exit the process instead of swallowing the error.

Actors that support Actor Standby can still be started in standard mode, for example from the Console or via the API.
To find out in which mode was the Actor started, you can read the `metaOrigin` option in `Actor.config`, or the `APIFY_META_ORIGIN` environment variable in case you're not using the Apify SDK.
If it is equal to `STANDBY`, the Actor was started in Standby mode, otherwise it was started in standard mode.
## Detect the run mode

Users can still start a Standby Actor in standard mode, for example from Apify Console or through the API. To find out which mode the Actor started in, read the `metaOrigin` option in `Actor.config`, or the `APIFY_META_ORIGIN` environment variable if you don't use the Apify SDK. The value `STANDBY` means Standby mode. Otherwise, the Actor started in standard mode.

<Tabs groupId="main">
<TabItem value="JavaScript" label="JavaScript">

```js
```javascript
import { Actor } from 'apify';

await Actor.init();
Expand All @@ -163,48 +186,22 @@ from apify import Actor
async def main() -> None:
async with Actor:
if Actor.configuration.meta_origin == 'STANDBY':
# Start your Standby server here
... # Start your Standby server here
else:
# Perform the standard Actor operations here
... # Perform the standard Actor operations here
```

</TabItem>
</Tabs>

## Run lifecycle in Standby mode

The platform starts and stops Standby runs automatically based on the incoming request load. It stops a run that receives no requests within the configured idle timeout and starts a new run when requests arrive again. Don't keep data only in the run's memory: persist anything you need to a [dataset or key-value store](../../../storage/index.md). See [how Standby scaling works](../../running/actor_standby.md#is-there-any-scaling-to-accommodate-the-incoming-requests) and [how to customize the Standby configuration](../../running/actor_standby.md#how-do-i-customize-standby-configuration).

Apart from the [readiness probe](#readiness-probe), the platform doesn't check your server's health while the run is alive. A run ends when its process exits, when it migrates to another machine, or when it stays idle for longer than the idle timeout. A server that stays up but stops responding keeps receiving requests, so on an unrecoverable error, exit the process instead of swallowing the error.

## Timeouts

When you send a request to an Actor in Standby mode, the total timeout for receiving the first response is _5 minutes_. Before the platform forwards the request to a specific Actor run, it performs a _run selection_ process to determine the specific Actor run that will handle it. This process has internal timeout of _2 minutes_.

## Get the URL of the Standby Actor

The URL is exposed as an environment variable `ACTOR_STANDBY_URL`. You can also use `Actor.config`, where the `standbyUrl` option is available.

The URL typically combines the Actor owner's username and the Actor name, for example:

```text
https://jane-doe--my-actor.apify.actor
```

The Actor also responds on a URL built from its ID, which keeps working if the Actor or its owner is renamed:

```text
https://92c4oi4fpzy7rprlf.apify.actor
```

Unlike the [container web server](./container_web_server.md) URL, which changes with every run, the Standby URL stays the same for all runs of the Actor. You can share it publicly or hardcode it in applications that call the Actor: copy it from the **Endpoints** tab on the Actor's detail page. Don't build the URL from the username and Actor name, because some Actors use a different hostname format.
## Standby URL

If the Actor exposes an MCP server, its endpoint is the Standby URL followed by the path defined in the [`webServerMcpPath`](../actor_definition/actor_json.md) property.
Each Standby Actor has a URL that stays the same for all of its runs. The URL is exposed as the `ACTOR_STANDBY_URL` environment variable and as the `standbyUrl` option in `Actor.config`.

Requests to the Standby URL require an Apify API token. See [how to authenticate your requests](../../running/actor_standby.md#how-do-i-authenticate-my-requests).
Unlike the Standby URL, the [container web server](./container_web_server.md) URL changes with every run. For the URL formats and where users find them, see [Standby URLs](../../running/actor_standby.md#standby-urls).

## Monetization of Actors in Standby mode
Requests to the Standby URL require an Apify API token; see [how to authenticate requests](../../running/actor_standby.md#authenticate-requests). If your Actor exposes an MCP server, define the endpoint path with the [`webServerMcpPath`](../actor_definition/actor_json.md) property; see [Use Standby Actors as MCP servers](../../running/actor_standby.md#use-standby-actors-as-mcp-servers).

You can monetize Standby Actors just like any other Actor.
## Monetize Standby Actors

For best results with Standby workflows, use the [pay-per-event pricing model](/actors/monetize/pay-per-event). In this model, users cover both the platform usage costs of their runs, as well as the event costs.
You can monetize Standby Actors just like any other Actor. For best results with Standby workflows, use the [pay-per-event pricing model](/actors/monetize/pay-per-event). In this model, users cover both the platform usage costs of their runs and the event costs.
Loading
Loading