
Apify Actorization
- 8.9k installs
- 2.3k repo stars
- Updated June 25, 2026
- apify/agent-skills
apify-actorization is an agent skill that Convert existing projects into Apify Actors - serverless cloud programs. Actorize JavaScript/TypeScript (SDK with Actor.init/exit), Python (async context manage.
About
Convert existing projects into Apify Actors - serverless cloud programs. Actorize JavaScript/TypeScript (SDK with Actor.init/exit), Python (async context manager), or any language (CLI wrapper). Use when migrating code to Apify, wrapping CLI tools as Actors, or adding Actor SDK to existing projects. --- name: apify-actorization description: Convert existing projects into Apify Actors - serverless cloud programs. Actorize JavaScript/TypeScript (SDK with Actor.init/exit), Python (async context manager), or any language (CLI wrapper). Use when migrating code to Apify, wrapping CLI tools as Actors, or adding Actor SDK to existing projects. --- # Apify Actorization Actorization converts existing software into reusable serverless applications compatible with the Apify platform. Actors are programs packaged as Docker images that accept well-defined JSON input, perform an action, and optionally produce structured JSON output. Run `apify init` in project root 2. Wrap code with SDK lifecycle (see language-specific section below) 3.
- Run `apify init` in project root
- Wrap code with SDK lifecycle (see language-specific section below)
- Configure `.actor/input_schema.json`
- Test with `apify run --input '{"key": "value"}'`
- Deploy with `apify push`
Apify Actorization by the numbers
- 8,917 all-time installs (skills.sh)
- +318 installs in the week ending Jul 28, 2026 (Skillselion tracking)
- Ranked #75 of 1,881 Marketing & SEO skills by installs in the Skillselion catalog
- Security screen: CRITICAL risk (skills.sh audit)
- Data as of Jul 28, 2026 (Skillselion catalog sync)
apify-actorization capabilities & compatibility
- Capabilities
- run `apify init` in project root · wrap code with sdk lifecycle (see language speci · configure `.actor/input_schema.json` · test with `apify run input '{"key": "value"}'` · deploy with `apify push`
- Use cases
- documentation
What apify-actorization says it does
--- name: apify-actorization description: Convert existing projects into Apify Actors - serverless cloud programs.
Actorize JavaScript/TypeScript (SDK with Actor.init/exit), Python (async context manager), or any language (CLI wrapper).
Use when migrating code to Apify, wrapping CLI tools as Actors, or adding Actor SDK to existing projects.
--- # Apify Actorization Actorization converts existing software into reusable serverless applications compatible with the Apify platform.
npx skills add https://github.com/apify/agent-skills --skill apify-actorizationAdd your badge
Show developers this skill is listed on Skillselion. Paste this into your README.
| Installs | 8.9k |
|---|---|
| repo stars | ★ 2.3k |
| Security audit | 1 / 3 scanners passed |
| Last updated | June 25, 2026 |
| Repository | apify/agent-skills ↗ |
What problem does apify-actorization solve for developers using this skill?
Convert existing projects into Apify Actors - serverless cloud programs. Actorize JavaScript/TypeScript (SDK with Actor.init/exit), Python (async context manager), or any language (CLI wrapper). Use w
Who is it for?
Developers who need apify-actorization patterns described in the cached skill documentation.
Skip if: Skip when docs are empty or the task is outside the skill's documented scope.
When should I use this skill?
Convert existing projects into Apify Actors - serverless cloud programs. Actorize JavaScript/TypeScript (SDK with Actor.init/exit), Python (async context manager), or any language (CLI wrapper). Use w
What you get
Actionable workflows and conventions from SKILL.md for apify-actorization.
- Apify Actor project
- Docker image configuration
Files
Apify Actorization
Actorization converts existing software into reusable serverless applications compatible with the Apify platform. Actors are programs packaged as Docker images that accept well-defined JSON input, perform an action, and optionally produce structured JSON output.
Quick start
1. Run apify init in project root 2. Wrap code with SDK lifecycle (see language-specific section below) 3. Configure .actor/input_schema.json 4. Test with apify run --input '{"key": "value"}' 5. Deploy with apify push
When to use this skill
- Converting an existing project to run on the Apify platform
- Adding Apify SDK integration to a project
- Wrapping a CLI tool or script as an Actor
- Migrating a Crawlee project to Apify
Prerequisites
Verify apify CLI is installed:
apify --helpIf not installed, use one of these methods (listed in order of preference):
# Preferred: install via a package manager (provides integrity checks)
npm install -g apify-cli
# Or (Mac): brew install apify-cliSecurity note: Do NOT install the CLI by piping remote scripts to a shell
(e.g.curl ... | bashorirm ... | iex). Always use a package manager.
Verify CLI is logged in:
apify info # Should return your usernameIf not logged in, authenticate using OAuth (opens browser):
apify loginIf browser login isn't available (headless environment or CI), ensure the APIFY_TOKEN environment variable is exported (note: the variable is APIFY_TOKEN, not APIFY_API_TOKEN). The CLI reads it automatically - no explicit login needed. If the user doesn't have a token, generate one at https://console.apify.com/settings/integrations.
Apify platform environment: When the Actor runs on the Apify platform,APIFY_TOKENis auto-injected as an environment variable and the Apify SDK reads it automatically — you do not need to pass it explicitly. Locally,apify loginstores credentials in~/.apifyand the SDK uses them.
Security note: Avoid passing tokens as command-line arguments (e.g. apify login -t <token>).Arguments are visible in process listings and may be recorded in shell history.
Prefer OAuth login or environment variables instead.
Never log, print, or embed APIFY_TOKEN in source code or configuration files.Use a token with the minimum required permissions (scoped token) and rotate it periodically.
Actorization checklist
Copy this checklist to track progress:
- [ ] Step 1: Analyze project (language, entry point, inputs, outputs)
- [ ] Step 2: Run
apify initto create Actor structure - [ ] Step 3: Apply language-specific SDK integration
- [ ] Step 4: Configure
.actor/input_schema.json - [ ] Step 5: Configure
.actor/output_schema.json(if applicable) - [ ] Step 6: Update
.actor/actor.jsonmetadata - [ ] Step 7: Write README.md for Apify Store listing
- [ ] Step 8: Test locally with
apify run - [ ] Step 9: Deploy with
apify push
Step 1: Analyze the project
Before making changes, understand the project:
1. Identify the language - JavaScript/TypeScript, Python, or other 2. Find the entry point - The main file that starts execution 3. Identify inputs - Command-line arguments, environment variables, config files 4. Identify outputs - Files, console output, API responses 5. Check for state - Does it need to persist data between runs?
Step 2: Initialize Actor structure
Run in the project root:
apify initThis creates:
.actor/actor.json- Actor configuration and metadata.actor/input_schema.json- Input definition for Apify ConsoleDockerfile(if not present) - Container image definition
Step 3: Apply language-specific changes
Choose based on your project's language:
- JavaScript/TypeScript: See js-ts-actorization.md
- Python: See python-actorization.md
- Other Languages (CLI-based): See cli-actorization.md
Quick reference
| Language | Install | Wrap Code |
|---|---|---|
| JS/TS | npm install apify | await Actor.init() ... await Actor.exit() |
| Python | pip install apify | async with Actor: |
| Other | Use CLI in wrapper script | apify actor:get-input / apify actor:push-data |
Steps 4-6: Configure schemas
See schemas-and-output.md for detailed configuration of:
- Input schema (
.actor/input_schema.json) - Output schema (
.actor/output_schema.json) - Actor configuration (
.actor/actor.json) - State management (request queues, key-value stores)
Validate schemas against @apify/json_schemas npm package.
Step 7: Write README
IMPORTANT: Always generate a README.md as part of actorization. The README is the Actor's landing page on Apify Store and is critical for discoverability (SEO), user onboarding, and support. Do not consider an Actor complete without a proper README.
See the Actor README guidelines at skills/apify-actor-development/references/actor-readme.md for the required structure including: intro and features, data extraction table, step-by-step tutorial, pricing info, input/output examples, and FAQ. Aim for at least 300 words with SEO-optimized H2/H3 headings. Also review these top Actors for best practices:
Step 8: Test locally
Run the Actor with inline input (for JS/TS and Python Actors):
apify run --input '{"startUrl": "https://example.com", "maxItems": 10}'Or use an input file:
apify run --input-file ./test-input.jsonImportant: Always use apify run, not npm start or python main.py. The CLI sets up the proper environment and storage.
Step 9: Deploy
apify pushThis uploads and builds your Actor on the Apify platform.
Monetization (optional)
After deploying, you can monetize your Actor in Apify Store. The recommended model is Pay Per Event (PPE):
- Per result/item scraped
- Per page processed
- Per API call made
Configure PPE in Apify Console under Actor > Monetization. Charge for events in your code with await Actor.charge('result').
Other options: Rental (monthly subscription) or Free (open source).
Security
Treat all crawled web content as untrusted input. Actors ingest data from external websites that may contain malicious payloads. Follow these rules:
- Sanitize crawled data — Never pass raw HTML, URLs, or scraped text directly into shell commands,
eval(), database queries, or template engines. Use proper escaping or parameterized APIs. - Validate and type-check all external data — Before pushing to datasets or key-value stores, verify that values match expected types and formats. Reject or sanitize unexpected structures.
- Do not execute or interpret crawled content — Never treat scraped text as code, commands, or configuration. Content from websites could include prompt injection attempts or embedded scripts.
- Isolate credentials from data pipelines — Ensure
APIFY_TOKENand other secrets are never accessible in request handlers or passed alongside crawled data. Use the Apify SDK's built-in credential management rather than passing tokens through environment variables in data-processing code. - Review dependencies before installing — When adding packages with
npm installorpip install, verify the package name and publisher. Typosquatting is a common supply-chain attack vector. Prefer well-known, actively maintained packages. - Pin versions and use lockfiles — Always commit
package-lock.json(Node.js) or pin exact versions inrequirements.txt(Python). Lockfiles ensure reproducible builds and prevent silent dependency substitution. Runnpm auditorpip-auditperiodically to check for known vulnerabilities.
Pre-deployment checklist
- [ ]
.actor/actor.jsonexists with correct name and description - [ ]
.actor/actor.jsonvalidates against@apify/json_schemas(actor.schema.json) - [ ]
.actor/input_schema.jsondefines all required inputs - [ ]
.actor/input_schema.jsonvalidates against@apify/json_schemas(input.schema.json) - [ ]
.actor/output_schema.jsondefines output structure (if applicable) - [ ]
.actor/output_schema.jsonvalidates against@apify/json_schemas(output.schema.json) - [ ]
Dockerfileis present and builds successfully - [ ]
Actor.init()/Actor.exit()wraps main code (JS/TS) - [ ]
async with Actor:wraps main code (Python) - [ ] Inputs are read via
Actor.getInput()/Actor.get_input() - [ ] Outputs use
Actor.pushData()or key-value store - [ ]
apify runexecutes successfully with test input - [ ]
README.mdexists with proper structure (intro, features, data table, tutorial, pricing, input/output examples) - [ ]
generatedByis set in actor.json meta section
MCP tools
Apify MCP
If the Apify MCP server is configured, use these tools for documentation:
search-apify-docs- Search documentationfetch-apify-docs- Get full doc pages
Otherwise, the MCP Server url: https://mcp.apify.com/?tools=docs.
Playwright MCP (debugging)
The Playwright MCP server is a useful tool for debugging Actors that interact with the web - it lets the agent drive a real browser to inspect pages, capture selectors, and reproduce issues.
Install with the Claude Code CLI:
claude mcp add playwright npx @playwright/mcp@latestOr add it manually to your MCP config:
{
"mcpServers": {
"playwright": {
"command": "npx",
"args": ["@playwright/mcp@latest"]
}
}
}Resources
- Actorization Academy - Comprehensive guide
- Apify SDK for JavaScript - Full SDK reference
- Apify SDK for Python - Full SDK reference
- Apify CLI Reference - CLI commands
- Actor Specification - Complete specification
CLI-based Actorization
For languages without an SDK (Go, Rust, Java, etc.), create a wrapper script that uses the Apify CLI.
Create wrapper script
Create start.sh in project root:
#!/bin/bash
set -e
# Get input from Apify key-value store
INPUT=$(apify actor:get-input)
# Parse input values (adjust based on your input schema)
MY_PARAM=$(echo "$INPUT" | jq -r '.myParam // "default"')
# Run your application with the input
./your-application --param "$MY_PARAM"
# If your app writes to a file, push it to key-value store
# apify actor:set-value OUTPUT --contentType application/json < output.json
# Or push structured data to dataset
# apify actor:push-data '{"result": "value"}'Update Dockerfile
Reference the cli-start template Dockerfile which includes the ubi utility for installing binaries from GitHub releases.
FROM apify/actor-node:20
# Install ubi for easy GitHub release installation
RUN curl --silent --location \
https://raw.githubusercontent.com/houseabsolute/ubi/master/bootstrap/bootstrap-ubi.sh | sh
# Install your CLI tool from GitHub releases (example)
# RUN ubi --project your-org/your-tool --in /usr/local/bin
# Or install apify-cli and jq manually
RUN npm install -g apify-cli
RUN apt-get update && apt-get install -y jq
# Copy your application
COPY . .
# Build your application if needed
# RUN ./build.sh
# Make start script executable
RUN chmod +x start.sh
# Run the wrapper script
CMD ["./start.sh"]Testing CLI-based Actors
For CLI-based Actors (shell wrapper scripts), you may need to test the underlying application directly with mock input, as apify run requires a Node.js or Python entry point.
Test your wrapper script locally:
# Set up mock input
export INPUT='{"myParam": "test-value"}'
# Run wrapper script
./start.shCLI commands reference
| Command | Description |
|---|---|
apify actor:get-input | Get input JSON from key-value store |
apify actor:set-value KEY | Store value in key-value store |
apify actor:push-data JSON | Push data to dataset |
apify actor:get-value KEY | Retrieve value from key-value store |
JavaScript/TypeScript Actorization
Install the Apify SDK
npm install apifyWrap main code with Actor lifecycle
import { Actor } from 'apify';
// Initialize connection to Apify platform
await Actor.init();
// ============================================
// Your existing code goes here
// ============================================
// Example: Get input from Apify Console or API
const input = await Actor.getInput();
console.log('Input:', input);
// Example: Your crawler or processing logic
// const crawler = new PlaywrightCrawler({ ... });
// await crawler.run([input.startUrl]);
// Example: Push results to dataset
// await Actor.pushData({ result: 'data' });
// ============================================
// End of your code
// ============================================
// Graceful shutdown
await Actor.exit();Key points
Actor.init()configures storage to use Apify API when running on platformActor.exit()handles graceful shutdown and cleanup- Both calls must be awaited
- Local execution remains unchanged - the SDK automatically detects the environment
Crawlee projects
Crawlee projects require minimal changes - just wrap with Actor lifecycle:
import { Actor } from 'apify';
import { PlaywrightCrawler } from 'crawlee';
await Actor.init();
// Get and validate input
const input = await Actor.getInput();
const {
startUrl = 'https://example.com',
maxItems = 100,
} = input ?? {};
let itemCount = 0;
const crawler = new PlaywrightCrawler({
requestHandler: async ({ page, request, pushData }) => {
if (itemCount >= maxItems) return;
const title = await page.title();
await pushData({ url: request.url, title });
itemCount++;
},
});
await crawler.run([startUrl]);
await Actor.exit();Express/HTTP servers
For web servers, use standby mode in actor.json:
{
"actorSpecification": 1,
"name": "my-api",
"usesStandbyMode": true
}Then implement readiness probe. See standby-mode.md.
Batch processing scripts
import { Actor } from 'apify';
await Actor.init();
const input = await Actor.getInput();
const items = input.items || [];
for (const item of items) {
const result = processItem(item);
await Actor.pushData(result);
}
await Actor.exit();Python Actorization
Install the Apify SDK
pip install apifyWrap main function with Actor context manager
import asyncio
from apify import Actor
async def main() -> None:
async with Actor:
# ============================================
# Your existing code goes here
# ============================================
# Example: Get input from Apify Console or API
actor_input = await Actor.get_input()
print(f'Input: {actor_input}')
# Example: Your crawler or processing logic
# crawler = PlaywrightCrawler(...)
# await crawler.run([actor_input.get('startUrl')])
# Example: Push results to dataset
# await Actor.push_data({'result': 'data'})
# ============================================
# End of your code
# ============================================
if __name__ == '__main__':
asyncio.run(main())Key points
async with Actor:handles both initialization and cleanup- Automatically manages platform event listeners and graceful shutdown
- Local execution remains unchanged - the SDK automatically detects the environment
Crawlee Python projects
import asyncio
from apify import Actor
from crawlee.playwright_crawler import PlaywrightCrawler
async def main() -> None:
async with Actor:
# Get and validate input
actor_input = await Actor.get_input() or {}
start_url = actor_input.get('startUrl', 'https://example.com')
max_items = actor_input.get('maxItems', 100)
item_count = 0
async def request_handler(context):
nonlocal item_count
if item_count >= max_items:
return
title = await context.page.title()
await context.push_data({'url': context.request.url, 'title': title})
item_count += 1
crawler = PlaywrightCrawler(request_handler=request_handler)
await crawler.run([start_url])
if __name__ == '__main__':
asyncio.run(main())Batch processing scripts
import asyncio
from apify import Actor
async def main() -> None:
async with Actor:
actor_input = await Actor.get_input() or {}
items = actor_input.get('items', [])
for item in items:
result = process_item(item)
await Actor.push_data(result)
if __name__ == '__main__':
asyncio.run(main())Schemas and output configuration
Input schema
Map your application's inputs to .actor/input_schema.json. Validate against the JSON Schema from the @apify/json_schemas npm package (input.schema.json).
{
"title": "My Actor Input",
"type": "object",
"schemaVersion": 1,
"properties": {
"startUrl": {
"title": "Start URL",
"type": "string",
"description": "The URL to start processing from",
"editor": "textfield",
"prefill": "https://example.com"
},
"maxItems": {
"title": "Max Items",
"type": "integer",
"description": "Maximum number of items to process",
"default": 100,
"minimum": 1
}
},
"required": ["startUrl"]
}Mapping guidelines
- Command-line arguments → input schema properties
- Environment variables → input schema or Actor env vars in actor.json
- Config files → input schema with object/array types
- Flatten deeply nested structures for better UX
Output schema
Define output structure in .actor/output_schema.json. Validate against the JSON Schema from the @apify/json_schemas npm package (output.schema.json).
For table-like data (multiple items)
- Use
Actor.pushData()(JS) orActor.push_data()(Python) - Each item becomes a row in the dataset
For single files or blobs
- Use key-value store:
Actor.setValue()/Actor.set_value() - Get the public URL and include it in the dataset:
// Store file with public access
await Actor.setValue('report.pdf', pdfBuffer, { contentType: 'application/pdf' });
// Get the public URL
const storeInfo = await Actor.openKeyValueStore();
const publicUrl = `https://api.apify.com/v2/key-value-stores/${storeInfo.id}/records/report.pdf`;
// Include URL in dataset output
await Actor.pushData({ reportUrl: publicUrl });For multiple files with a common prefix (collections)
// Store multiple files with a prefix
for (const [name, data] of files) {
await Actor.setValue(`screenshots/${name}`, data, { contentType: 'image/png' });
}
// Files are accessible at: .../records/screenshots%2F{name}Actor configuration (actor.json)
Configure .actor/actor.json. Validate against the JSON Schema from the @apify/json_schemas npm package (actor.schema.json).
{
"actorSpecification": 1,
"name": "my-actor",
"title": "My Actor",
"description": "Brief description of what the Actor does",
"version": "1.0.0",
"meta": {
"templateId": "ts_empty",
"generatedBy": "Claude Code with Claude Opus 4.5"
},
"input": "./input_schema.json",
"dockerfile": "../Dockerfile"
}Important: Fill in the generatedBy property with the tool/model used.
State management
Request queue - for pausable task processing
The request queue works for any task processing, not just web scraping. Use a dummy URL with custom uniqueKey and userData for non-URL tasks:
const requestQueue = await Actor.openRequestQueue();
// Add tasks to the queue (works for any processing, not just URLs)
await requestQueue.addRequest({
url: 'https://placeholder.local', // Dummy URL for non-scraping tasks
uniqueKey: `task-${taskId}`, // Unique identifier for deduplication
userData: { itemId: 123, action: 'process' }, // Your custom task data
});
// Process tasks from the queue (with Crawlee)
const crawler = new BasicCrawler({
requestQueue,
requestHandler: async ({ request }) => {
const { itemId, action } = request.userData;
// Process your task using userData
await processTask(itemId, action);
},
});
await crawler.run();
// Or manually consume without Crawlee:
let request;
while ((request = await requestQueue.fetchNextRequest())) {
await processTask(request.userData);
await requestQueue.markRequestHandled(request);
}Key-value store - for checkpoint state
// Save state
await Actor.setValue('STATE', { processedCount: 100 });
// Restore state on restart
const state = await Actor.getValue('STATE') || { processedCount: 0 };Related skills
Forks & variants (2)
Apify Actorization has 2 known copies in the catalog totaling 14 installs. They canonicalize to this original listing.
How it compares
Choose apify-actorization when an existing codebase or CLI must become a reusable Apify cloud Actor rather than a one-off script.
FAQ
What does apify-actorization do?
Convert existing projects into Apify Actors - serverless cloud programs. Actorize JavaScript/TypeScript (SDK with Actor.init/exit), Python (async context manager), or any language (CLI wrapper). Use when migrating code t
When should I use apify-actorization?
Convert existing projects into Apify Actors - serverless cloud programs. Actorize JavaScript/TypeScript (SDK with Actor.init/exit), Python (async context manager), or any language (CLI wrapper). Use when migrating code t
Is apify-actorization safe to install?
Review the Security Audits panel on this page before installing in production.