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
14 changes: 14 additions & 0 deletions apify-api/openapi/paths/actors/acts@{actorId}@runs.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -275,6 +275,20 @@ post:
schema:
type: string
example: dGhpcyBpcyBqdXN0IGV4YW1wbGUK...
- name: forcePermissionLevel
in: query
description: |
Overrides the Actor's configured permission level for this run only. Useful for testing limited permissions
before migrating your Actor or temporarily elevating/restricting access. If not provided, the Actor's default
permission level is used. For more information on permissions see [the documentation](https://docs.apify.com/platform/actors/development/permissions)
style: form
explode: true
schema:
type: string
enum:
- LIMITED_PERMISSIONS
- FULL_PERMISSIONS
example: LIMITED_PERMISSIONS
requestBody:
description: ''
content:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -861,7 +861,8 @@ Example of multiple datasets input:
"title": "Datasets",
"type": "array",
"description": "Select multiple datasets",
"resourceType": "dataset"
"resourceType": "dataset",
"resourcePermissions": ["READ"]
}
```

Expand All @@ -876,6 +877,7 @@ Rendered input:
| `type` | `string` | Yes | Specifies the type of input - `string` for single value. |
| `editor` | One of <ul><li>`resourcePicker`</li><li>`textfield`</li><li>`hidden`</li></ul> | No | Visual editor used for <br/>the input field. Defaults to `resourcePicker`. |
| `resourceType` | One of <ul><li>`dataset`</li><li>`keyValueStore`</li><li>`requestQueue`</li></ul> | Yes | Type of Apify Platform resource |
| `resourcePermissions` | Array of strings; allowed values: <ul><li>`READ`</li><li>`WRITE`</li></ul> | Yes | Permissions requested for the referenced resource. Use [\"READ\"] for read-only access, or [\"READ\", \"WRITE\"] to allow writes.|
| `pattern` | String | No | Regular expression that will be used to validate the input. If validation fails, the Actor will not run. |
| `minLength` | Integer | No | Minimum length of the string. |
| `maxLength` | Integer | No | Maximum length of the string. |
Expand All @@ -887,5 +889,22 @@ Rendered input:
| `type` | `array` | Yes | Specifies the type of input - `array` for multiple values. |
| `editor` | One of <ul><li>`resourcePicker`</li><li>`hidden`</li></ul> | No | Visual editor used for <br/>the input field. Defaults to `resourcePicker`. |
| `resourceType` | One of <ul><li>`dataset`</li><li>`keyValueStore`</li><li>`requestQueue`</li></ul> | Yes | Type of Apify Platform resource |
| `resourcePermissions` | Array of strings; allowed values: <ul><li>`READ`</li><li>`WRITE`</li></ul> | Yes | Permissions requested for the referenced resources. Use [\"READ\"] for read-only access, or [\"READ\", \"WRITE\"] to allow writes. Applies to each selected resource. |
| `minItems` | Integer | No | Minimum number of items the array can contain. |
| `maxItems` | Integer | No | Maximum number of items the array can contain. |

#### Resource permissions

If your Actor runs with limited permissions it needs to declare what kind of access needs to the resources supplied via the input. The `resourcePermissions` field expresses **what operations your Actor needs on the user-selected storages**. It is evaluated at run start and used to expand a [Limited-permissions Actors](../../permissions/index.md#) scope to be able to access the resource sent via Actor's input.

- `["READ"]` — the Actor may read from the referenced resources.
- `["READ", "WRITE"]` — the Actor may read and write to the referenced resources.

:::note Keep in mind

- This setting does not change field visibility or it being required in the UI; it only defines runtime access for the selected resources.
- For array fields (`type: array`), the same permissions apply to **each** selected resource.
- If your Actor attempts an operation without the requested permission (e.g., attempts to write with a read-only access), the run will fail with an insufficient-permissions error.
- Your users will [see what permissions you require in the input's tooltip](../../../running/permissions.md#recognizing-permission-levels-in-console-and-store)

:::
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is the copy that needs to be updated. Let's not forget about updating this screenshot as well.

Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
131 changes: 131 additions & 0 deletions sources/platform/actors/development/permissions/index.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,131 @@
---
title: Permissions
description: Learn how to declare and manage permissions for your Actor, what access levels mean, and how to build secure, trusted Actors for Apify users.
sidebar_position: 7.5
slug: /actors/development/permissions
---

**Learn how to declare and manage permissions for your Actor, what permission levels mean, and how to build secure, trusted Actors for Apify users.**

---

Every time a user runs your Actor, it runs under their Apify account. **Actor Permissions** is an Actor level setting that defines the level of access your Actor needs to be able to run. This gives users transparency and control over what data your Actor can access, building trust in your tools.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

(nit) This intro paragraph reads a bit awkward to me. Not sure what "access" means.... also I'd mention the inspiration from "sandboxed" apps on mobile permissions.


There are two levels of access your Actors can request:

- **Limited permissions (default):** Actors with this permission level have restricted access, primarily to their own storages and the data they generate. They cannot access other user data on the Apify platform.
- **Full permissions:** This level grants an Actor access to all of a user's Apify account data.

Most Actors should use limited permissions to request only the specific access they need and reserve full permissions for exceptional cases where the Actor cannot function otherwise.

## How Actor permissions work

When a user runs an Actor, it receives an Apify API token. This token is injected to the Actor's runtime and has a scope of access as requested by the Actor's permission level.

Actors with **full permissions** receive a token that grants complete access to the user's Apify account via the Apify API.

Actors with **limited permissions** receive [a restricted scoped token](../../../integrations/programming/api.md#api-tokens-with-limited-permissions). This token only allows the Actor to perform a specific set of actions, which covers the vast majority of common use cases.

A limited-permission Actor can:

- Read and write to its default storages.
- Update the current run’s status, abort the run, or [metamorph](../programming_interface/metamorph.md) to another Actor (as long as it also has limited permissions).
- Read basic user information (whether the user is paying, their proxy password or public profile) from the environment.
- Read and/or write to storages provided via Actor input (sample scenario: the user provides the Actor with a dataset that the Actor should write into).
- Run any other Actor with limited permissions.
- Create any additional storage, and write to that storage.
- Read and write to storages created in previous runs.

This approach ensures your Actor has everything it needs to function while protecting user data from unnecessary exposure.

:::info

To learn how to migrate your Actors to run under limited permissions, see the [Migration guide](./migration_guide.md)

:::

### Declaring permissions

You can set the permission level for your Actor in the Apify Console under its **Settings** tab. All the existing Actors are configured to use full permissions, but the plan is to make limited permissions the default for all new Actors.

![Actor permissions configuration in Actor settings](./images/actor_settings_permissions.webp)

### End-user experience

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is a repetition of the "Impact of Permission Level" section below. Maybe just remove this and move the screenshot to that section?

Copy link
Contributor Author

@raethlo raethlo Nov 6, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

3a0c308 Decided to leave the end user experience section and move the implications section(+your suggestions) to the warning admonition.


Currently, users will see a visible permission badge on your Actor's detail page indicating whether it requires "Limited permissions" or "Full permissions". At this stage, the experience of running an Actor will not change for the user.

![User experience for users viewing limited permission Actor in console](./images/end_user_ux_limited_permissions.png)

![User experience for users viewing full permission Actor in console](./images/end_user_ux_full_permissions.png)

:::warning

Actor permissions are a new feature. With the initial release, the distinction between full-permissions and limited-permissions Actors is primarily informational, but it will become increasingly significant over time.

Future changes may include:
- Stronger confirmations and/or warnings added when running full-permissions Actors
- Actors requiring full permissions may receive a lower [Actor Quality score](../../publishing/quality_score.mdx), which can reduce their ranking in the store.
- Some platform features and recommendations may prioritize limited-permissions Actors by default.

Whenever possible, design your Actors to use limited permissions and request only access they truly need.

:::


### Accessing user provided storages

Limited-permissions Actors can access storages that users explicitly provide via the Actor input. Use the input schema to add a storage picker and declare exactly which operations your Actor needs.

- Add a field with `editor: "resourcePicker"`.
- Set `resourceType` to one of `dataset`, `keyValueStore`, or `requestQueue`.
- Specify `resourcePermissions` with the minimal required scope: `"READ"` or `"READ", "WRITE"`.

Example input schema field (single resource):

```json
{
"title": "Output dataset",
"type": "string",
"editor": "resourcePicker",
"resourceType": "dataset",
"resourcePermissions": ["READ", "WRITE"]
}
```

Selecting multiple resources:

- Use `type: "array"` to let users choose more than one storage.
- The same `resourcePermissions` apply to each selected resource.

```json
{
"title": "Source datasets",
"type": "array",
"editor": "resourcePicker",
"resourceType": "dataset",
"resourcePermissions": ["READ"],
"minItems": 1
}
```

Behavior at run time:

- The user’s selection is injected into the run input, and the run token is expanded to allow only the requested operations on the selected storages.
- If your code attempts an operation not covered by `resourcePermissions` (for example, writing with only `READ`), the platform returns an insufficient-permissions error.

See the full [input schema reference for details.](../actor_definition/input_schema/specification.md).

### Requesting full permissions

Designing your Actors to work under limited permissions is the recommended approach, it helps improve your Actor’s [Actor Quality score](../../publishing/quality_score.mdx#trustworthiness) and increases user trust and adoption. However, some use cases do legitimately require broader access to user data (e.g., to perform administrative tasks or orchestrate other Actors). If your Actor falls in this category or cannot function with limited permissions for another reason:

- Explain why you need full permissions in your Actor's README. This will help keep user trust and set correct user expectations.
- Set the permission level in the Actor’s **Settings** in Console to **Full permissions**.
- Be aware of the [UX implications](#end-user-experience) and impact on [Actor Quality score](../../publishing/quality_score.mdx) for full-permission Actors.


:::info

Actor permissions are a new feature. If something is preventing you from migrating to limited permissions or you have a use case that you think should work under limited permissions and it does not, please reach out to support or talk to us on [the community forum](https://discord.com/invite/crawlee-apify-801163717915574323).

:::
146 changes: 146 additions & 0 deletions sources/platform/actors/development/permissions/migration_guide.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,146 @@
---
title: Migration guide
description: How to migrate your Actor to limited permissions. Common migration paths, code examples, and common issues.
sidebar_position: 9
slug: /actors/development/permissions/migration-guide
---

**Migrate your Actor to limited permissions, review common migration paths, code examples, and solutions to common issues.**

---

Use this guide to migrate existing Actors to use [limited permissions](index.md#how-actor-permissions-work). The general prerequisite is to update to the latest [Apify SDK](https://docs.apify.com/sdk).

Recommended minimum SDK versions:

- JavaScript SDK: [apify@3.4.4](https://github.com/apify/apify-sdk-js/releases/tag/apify%403.4.4)
- Python SDK: [v3.0.0](https://github.com/apify/apify-sdk-python/releases/tag/v3.0.0)

Before you start it's helpful to understand [what access restrictions limited permission impose](index.md#how-actor-permissions-work).

## How to test my Actor with limited permissions before migrating

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How to test your Actor... (for consistency with the rest of the copy)


You can override permission level for a single run using run options under Actor Source tab in Console:

![Force Actor permissions for a single runs.](./images/actor_run_permission_override.png)

Force Actor permissions for a single runs.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This line is extraneous I think. Remove.


You can do the same using Apify Client as well:

```tsx
await apifyClient.actor(actorId).call(input, {
forcePermissionLevel: ACTOR_PERMISSION_LEVEL.LIMITED_PERMISSIONS,
});
```

Or using just API:

```tsx
POST https://api.apify.com/v2/acts/<actor_id>/runs?**forcePermissionLevel=LIMITED_PERMISSIONS**
```


## Common migration paths

We expect that most public Actors can be migrated to limited permissions with minor, if any, adjustments.

The general prerequisite is to **update the Actor to use the latest [Apify SDK](https://docs.apify.com/sdk)**. Below you can read a guide that covers various, more advanced cases.

Once you have updated and [tested](#how-to-test-my-actor-with-limited-permissions-before-migrating) your Actor, you can change the permissions in the Actor setting. The setting will take immediate effect.
Comment on lines +48 to +50

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe flip these two paragraphs, so that the scenarios follow directly after the line "Below you can read a guide..."


### The Actor only pushes data to default storages

This is the most common and simplest use case. If your Actor only reads its input and writes results to its default dataset, key-value store, or request queue, **no changes are needed**. Limited permissions fully support this behavior out of the box.

## The Actor calls other Actors

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

H3 (###)


An Actor with limited permissions can only call other Actors that also have limited permissions. If your Actor calls another one, you will need to ensure the target Actor has been migrated first.

## The Actor accesses storages provided by the user

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

H3 (###)


If your Actor is designed to read from or write to a storage that the user provides via an input field, you must explicitly declare what access you need in Actor’s schema.

1. Populate `resourceType` property on the field to enable the native resource picker.
2. Populate `resourcePermissions` with permissions you need for the resource.

Let’s say your Actor allows the user to provide a custom dataset that your Actor should output its result to. Your `input_schema.json` might contain something like this:

```json
{
"title": "Output",
"type": "string",
"description": "Select a dataset for the Actor results",
}
```

To support limited permissions, change it to this:

```json
{
"title": "Output",
"type": "string",
"description": "Select a dataset for the Actor results",
"resourceType": "dataset",
"resourcePermissions": ["READ", "WRITE"],
"editor": "textfield", // If you want to preserve the plain "string" input UI, instead of rich resource picker.
}
```

Now when the platform runs your Actor, it’ll automatically add the user provided storage the Actor’s scope so that it can access it.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

...to the Actor's scope...


:::info Backward compatibility

The user can provide the resource both via its name and its ID. If you have existing users with existing inputs that specify the resource via its name, this change to the input schema won’t break it.

:::

## The Actor accesses named storages

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

H3 (###)


Actors sometimes use named storages for caching or persisting state across runs. With limited permissions, an Actor can create a named storage on its first run and will automatically retain access to it in all subsequent runs by the same user.

If your Actor previously relied on accessing a pre-existing named storage, you will need to rename it in your code. This will cause the Actor to recreate the storage under the new system on its next run.

In order to achieve a smooth migration without disrupting your Actor’s users, you will need to make sure that your Actor can handle the transition. The suggested approach is the following:

1. Adjust the code of the Actor so that it can run with both limited and full permissions.
2. Change the Actor setting to limited permissions.
3. Clean up the migration code.

```ts
const OLD_CACHE_STORE_NAME = 'my-actor-cache';
const NEW_CACHE_STORE_NAME = 'my-actor-cache-updated';

let store;

if (process.env.ACTOR_PERMISSION_LEVEL === 'LIMITED_PERMISSIONS') {
// If the Actor is running with limited permissions and we need to create
// a new store. The platform will remember that the store was created by this Actor
// and will allow access in all follow-up runs.
store = await Actor.openKeyValueStore(NEW_CACHE_STORE_NAME);
} else {
// If the Actor is still running with full permissions and we should use
// the existing store.
store = await Actor.openKeyValueStore(OLD_CACHE_STORE_NAME);
}
```

:::info Re-create cache only under limited permissions.

The goal here is to create the new storage **only once the Actor runs with limited permissions**. Only that way the access is retained in follow-up runs.

:::

**If the existing contents of the named storage is critical for your Actor to keep functioning for the existing users** (as in, you can’t afford removing the storage), reach out to us. We can discuss the available options.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If the existing contents of the named storage are critical...

Also, is the emphasis necessary for such a long part of the sentence?


## The Actor needs to know whether the user is paying

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

H3 (###)


Some Actors have different logic for free and paying users. Previously you could retrieve this information by calling the `/users/me` API endpoint. However, Actors running under limited permissions don't have access to that endpoint, to get this information, your Actor should read the `APIFY_USER_IS_PAYING` environment variable, or directly use the SDK to obtain the value:

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

...don't have access to that endpoint. To get this information, ...


```ts
const { userIsPaying } = Actor.getEnv();
```

## The Actor uses proxy

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

H3 (###)
"a proxy"?
"the proxy feature"?


Similarly, if your Actor needs the user's proxy password, it should get it from the `APIFY_PROXY_PASSWORD` environment variable instead of calling the `/users/me` endpoint, or preferably just rely on the SDK to take care of the documentation.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

...endpoint, or preferably (remove double space after 'or')

Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@ Here's a table of key system environment variables:
| `APIFY_HEADLESS` | If **1**, web browsers inside the Actor should run in headless mode (no windowing system available). |
| `APIFY_IS_AT_HOME` | Contains **1** if the Actor is running on Apify servers. |
| `ACTOR_MEMORY_MBYTES` | Size of memory allocated for the Actor run, in megabytes. Can be used to optimize memory usage or finetuning of low-level external libraries. |
| `ACTOR_PERMISSION_LEVEL` | [Permission level](../../running/permissions.md) the Actor is run under. This determines what resources in the user’s account the Actor can access. |
| `APIFY_PROXY_PASSWORD` | Password for accessing Apify Proxy services. This password enables the Actor to utilize proxy servers on behalf of the user who initiated the Actor run. |
| `APIFY_PROXY_PORT` | TCP port number to be used for connecting to the Apify Proxy. |
| `APIFY_PROXY_STATUS_URL` | URL for retrieving proxy status information. Appending `?format=json` to this URL returns the data in JSON format for programmatic processing. |
Expand Down
Loading
Loading