# Selenium Python Script Runner (`vgvianna/selenium-python-script-runner`) Actor

Run Selenium Python scripts in the cloud without building and deploying your own Actor.

- **URL**: https://apify.com/vgvianna/selenium-python-script-runner.md
- **Developed by:** [Victor Gabriel Vianna](https://apify.com/vgvianna) (community)
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $4.00 / 1,000 managed runtime (30 seconds)s

This Actor is paid per event and usage. You are charged both the fixed price for specific events and for Apify platform usage.

Learn more: https://docs.apify.com/actors/running/actors-in-store.md#pay-per-event

## What's an Apify Actor?

Actors are web data automations that power AI and operations. They run on the Apify platform to scrape websites, process data, connect APIs, and automate workflows.
In Batch mode, an Actor accepts a well-defined JSON input, performs an action which can take anything from a few seconds to a few hours,
and optionally produces a well-defined JSON output, datasets with results, or files in key-value store.
In Standby mode, an Actor provides a web server which can be used as a website, API, or an MCP server.
Actors are written with capital "A".

## How to integrate an Actor?

If asked about integration, you help developers integrate Actors into their projects.
You adapt to their stack and deliver integrations that are safe, well-documented, and production-ready.
The best way to integrate Actors is as follows.

- **AI agents and MCP clients** — the [Apify MCP server](https://docs.apify.com/integrations/mcp.md) at `https://mcp.apify.com` (remote, streamable HTTP, OAuth on first use).
- **Agentic workflows and local Actor development** — [Agent Skills](https://apify.com/.well-known/agent-skills/index.json) with the [Apify CLI](https://docs.apify.com/cli/docs.md): `npm install -g apify-cli`, then `apify login`.
- **JavaScript/TypeScript projects** — the official [JS/TS client](https://docs.apify.com/api/client/js/docs.md): `npm install apify-client`.
- **Python projects** — the official [Python client](https://docs.apify.com/api/client/python/docs.md): `pip install apify-client`.
- **Any other language** — the [REST API](https://docs.apify.com/api/v2.md).

For usage examples, see the [API](#api) section below.

For more details, see Apify documentation as [Markdown index](https://docs.apify.com/llms.txt) and [Markdown full-text](https://docs.apify.com/llms-full.txt).

# README

## Selenium Python Script Runner

Run existing trusted Selenium Python scripts on Apify without creating, packaging, and deploying a separate Actor project.

Paste your Python script, optionally add normal PyPI dependencies, JSON input, secrets, or an Apify proxy, then run it from the Apify Console, API, or schedules.

Use this Actor when you already have Selenium code and want to move the execution to the cloud without rebuilding it around an Actor project.

### Minimal tested example

```python
from selenium import webdriver

driver = webdriver.Chrome()
driver.get("https://example.com")
print(driver.title)
driver.quit()
```

Chrome, ChromeDriver, Selenium, and an Xvfb display are already provided.

For ordinary Selenium scripts like the example above, you do not need to add:

- `main()`
- a ChromeDriver path
- `--headless`
- `--no-sandbox`

The runtime handles the required managed-container Chrome configuration at the infrastructure level rather than modifying your Selenium code.

### Inputs

- `code` **(required)**: Python code executed as an ordinary script.
- `requirements` **(optional)**: normal PyPI requirements, one per line. Direct URLs, VCS packages, local paths, index directives, and `-r` files are intentionally unsupported.
- `scriptInput` **(optional)**: arbitrary JSON. It is written to the JSON file identified by `RUNNER_INPUT_PATH`.
- `environmentVariables` **(optional, secret)**: string key/value pairs deliberately passed to your script, such as `USERNAME`, `PASSWORD`, or `API_KEY`.
- `scriptTimeoutSecs` **(optional)**: maximum user-script runtime from 1 to 900 seconds. Dependency setup has a separate 180-second limit.
- `proxyConfiguration` **(optional)**: Apify proxy configuration. When resolved, the proxy URL is exposed as `RUNNER_PROXY_URL`. Configure Selenium explicitly to use it; the Actor does not monkeypatch `webdriver.Chrome()`.

V1 uses a fixed **2 GB memory allocation**, validated in Apify Cloud with ordinary Chrome and longer-running browser execution.

Each run gets a fresh working directory and an ephemeral Python environment. Selenium and the Apify Python SDK are already available. Additional requirements are installed only inside the per-run environment and cannot modify the supervisor process.

### Runtime billing

When pay-per-event pricing is active, the Actor charges one managed-runtime block before managed work begins and another before each additional **30 seconds** of managed work.

The same runtime clock covers:

- Python environment setup
- dependency installation
- browser execution
- user-script execution

In V1, Apify platform usage is billed separately.

The Actor does **not** add a pay-per-event charge for items your script writes to the default Dataset.

If the run's spending limit cannot cover the next runtime block, the Actor stops the active process group cleanly and writes `OUTPUT` with:

```text
failureReason: "spending_limit_reached"
```

This distinguishes a budget limit from a Python error or timeout.

### Results and artifacts

Every run writes an `OUTPUT` record to the default Key-Value Store.

It contains information such as:

- execution status
- exit code
- duration
- bounded stdout and stderr
- truncation flags
- charged runtime blocks
- artifact metadata

Failed scripts and timeouts persist `OUTPUT` before the Actor run fails, so schedules and API integrations receive a real failure state rather than a silent success.

#### Generated files

Files written directly below the script working directory are copied to the default Key-Value Store.

Their original names and retrievable record keys are listed in `OUTPUT`.

Artifact record keys use the `artifacts.` prefix because Apify Key-Value Store record keys cannot contain filesystem paths.

Current limits are:

- maximum 50 files
- maximum 10 MiB per file
- maximum 50 MiB total

Runner internals, temporary inputs, and browser cache directories are excluded.

#### Chrome downloads

Normal Chrome downloads from the per-run `HOME/Downloads` directory are collected automatically.

Unusual download flows or browser configurations may require handling inside your own script.

#### Dataset

The default Dataset belongs to your script.

You can use the Apify Python SDK normally, for example:

```python
import asyncio

from apify import Actor

async def main():
    async with Actor:
        await Actor.push_data({"result": "ok"})

asyncio.run(main())
```

The runner does not add administrative rows to your Dataset.

### Security and scope

Run code you trust.

This Actor executes the Python code you provide. It is **not a security sandbox for untrusted third-party code**.

Operational controls include:

- a separate subprocess
- process-group cleanup
- execution timeouts
- an ephemeral per-run filesystem
- isolated dependency installation
- Apify Limited Permissions

These controls are designed for reliable execution, not hostile-code isolation.

The child process receives only required system settings, selected Apify runtime values, runner helper paths, and the values you explicitly provide through `environmentVariables`.

It does not inherit the supervisor environment wholesale.

Do not print secrets from your own script. User-script stdout and stderr are intentionally available in logs and in the bounded result summary.

### Compatibility

V1 supports:

- Python
- Selenium
- Chrome / Chromium
- normal PyPI dependencies
- Apify API and schedules
- Apify proxy configuration
- generated files and Chrome downloads
- Apify Dataset and Key-Value Store access

V1 is **not**:

- Selenium Grid
- a browser farm
- a generic Docker or VM runner
- a repository runner
- a hostile-code sandbox
- an anti-bot bypass service

The Actor is designed to make ordinary Selenium Python scripts easier to run on Apify, but it does not guarantee that every existing Selenium setup, system dependency, or Python package combination will run unchanged.

# Actor input Schema

## `code` (type: `string`):

Python code executed as a normal script. Selenium and Chrome are already available.

## `requirements` (type: `string`):

Optional PyPI package requirements, one per line. URLs, local paths, VCS installs, indexes, and requirements-file directives are not supported.

## `scriptInput` (type: `object`):

Arbitrary JSON written to the file named by RUNNER\_INPUT\_PATH.

## `environmentVariables` (type: `object`):

String key/value pairs deliberately passed to the script, for example USERNAME, PASSWORD, or API\_KEY.

## `scriptTimeoutSecs` (type: `integer`):

Maximum script runtime. Dependency installation has a separate fixed timeout.

## `proxyConfiguration` (type: `object`):

Optional Apify proxy configuration. When supplied, the resolved URL is exposed as RUNNER\_PROXY\_URL; configure Selenium yourself to use it.

## Actor input object example

```json
{
  "code": "import asyncio\n\nfrom apify import Actor\nfrom selenium import webdriver\n\ndriver = webdriver.Chrome()\ndriver.get(\"https://example.com\")\ntitle = driver.title\nprint(title)\ndriver.quit()\n\nasync def push_result():\n    async with Actor:\n        await Actor.push_data({\"title\": title})\n\nasyncio.run(push_result())\n",
  "scriptTimeoutSecs": 120
}
```

# Actor output Schema

## `runnerResult` (type: `string`):

Execution metadata is available as OUTPUT in the default Key-Value Store.

## `artifacts` (type: `string`):

Files retained from the script workdir have retrievable artifacts.\* record keys listed in OUTPUT in the default Key-Value Store.

# API

You can run this Actor programmatically using our API. Below are code examples in JavaScript, Python, and CLI, as well as the OpenAPI specification and MCP server setup.

## JavaScript example

```javascript
import { ApifyClient } from 'apify-client';

// Initialize the ApifyClient with your Apify API token
// Replace the '<YOUR_API_TOKEN>' with your token
const client = new ApifyClient({
    token: '<YOUR_API_TOKEN>',
});

// Prepare Actor input
const input = {
    "code": `import asyncio

from apify import Actor
from selenium import webdriver

driver = webdriver.Chrome()
driver.get("https://example.com")
title = driver.title
print(title)
driver.quit()

async def push_result():
    async with Actor:
        await Actor.push_data({"title": title})

asyncio.run(push_result())`
};

// Run the Actor and wait for it to finish
const run = await client.actor("vgvianna/selenium-python-script-runner").call(input);

// Fetch and print Actor results from the run's dataset (if any)
console.log('Results from dataset');
console.log(`💾 Check your data here: https://console.apify.com/storage/datasets/${run.defaultDatasetId}`);
const { items } = await client.dataset(run.defaultDatasetId).listItems();
items.forEach((item) => {
    console.dir(item);
});

// 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/js/docs

```

## Python example

```python
from apify_client import ApifyClient

# Initialize the ApifyClient with your Apify API token
# Replace '<YOUR_API_TOKEN>' with your token.
client = ApifyClient("<YOUR_API_TOKEN>")

# Prepare the Actor input
run_input = { "code": """import asyncio

from apify import Actor
from selenium import webdriver

driver = webdriver.Chrome()
driver.get(\"https://example.com\")
title = driver.title
print(title)
driver.quit()

async def push_result():
    async with Actor:
        await Actor.push_data({\"title\": title})

asyncio.run(push_result())
""" }

# Run the Actor and wait for it to finish
run = client.actor("vgvianna/selenium-python-script-runner").call(run_input=run_input)

# Fetch and print Actor results from the run's dataset (if there are any)
print(f"💾 Check your data here: https://console.apify.com/storage/datasets/{run.default_dataset_id}")
for item in client.dataset(run.default_dataset_id).iterate_items():
    print(item)

# 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/python/docs/quick-start

```

## CLI example

```bash
echo '{
  "code": "import asyncio\\n\\nfrom apify import Actor\\nfrom selenium import webdriver\\n\\ndriver = webdriver.Chrome()\\ndriver.get(\\"https://example.com\\")\\ntitle = driver.title\\nprint(title)\\ndriver.quit()\\n\\nasync def push_result():\\n    async with Actor:\\n        await Actor.push_data({\\"title\\": title})\\n\\nasyncio.run(push_result())\\n"
}' |
apify call vgvianna/selenium-python-script-runner --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,vgvianna/selenium-python-script-runner"
        }
    }
}
```

The hosted server signs you in with OAuth on first connect, so no API token belongs in this config. Clients without OAuth support can send an `Authorization: Bearer <APIFY_API_TOKEN>` header instead, using a token from API & Integrations in Apify Console (https://console.apify.com/settings/integrations).

## OpenAPI specification

Download the OpenAPI definition: https://api.apify.com/v2/actors/BvoYShwZZ8qM3pe7V/builds/K6pIp6Fk87RbkvAZL/openapi.json
