---
title: "Deploy Selenium with flask"
description: "[Jul'26] Deploy Flask API with remote Selenium for web scraping"
category: "Starters"
url: https://railway.com/deploy/selenium-flask
---

# Deploy Selenium with flask

[Jul'26] Deploy Flask API with remote Selenium for web scraping

**[Deploy Selenium with flask on Railway](https://railway.com/template/selenium-flask)**

- **Creator:** codestorm
- **Category:** Starters
- **Total deploys:** 11

## Template content

### flask https://devicons.railway.app/flask

- **Source:** codestorm-official/selenium-flask
- **Public domain:** Yes

### selenium https://www.gravatar.com/avatar/b2a8a002fd393d0cfd1158319054a026?s=120&r=g&d=404

- **Image:** selenium/standalone-chrome

## Documentation

# Deploy and Host Selenium with Flask on Railway

## What is Selenium with Flask?

Selenium with Flask is a lightweight browser automation stack for Railway. This template runs as two connected services: a Flask REST API service and a Selenium Standalone Chrome service.

The Flask service exposes HTTP endpoints that trigger browser automation tasks, while the Selenium service runs the remote Chrome browser environment. Communication between both services uses Selenium Remote WebDriver, making the setup cleaner, more scalable, and easier to maintain than bundling Chrome, ChromeDriver, and the API server into a single container.

## About Hosting Selenium with Flask

Hosting Selenium with Flask on Railway gives you a ready-to-use setup for building browser automation APIs, scraping workers, and internal automation tools.

This template separates the application layer and browser automation layer into two services:

* Flask REST API
  Handles incoming HTTP requests, API routes, scraping logic, and response formatting.

* Selenium Standalone Chrome
  Runs headless Chrome and exposes a Remote WebDriver endpoint for browser sessions.

Instead of installing ChromeDriver directly inside the Flask container, the Flask app connects to the Selenium service through a remote URL. When both services run inside Railway, you can use Railway private networking for internal service-to-service communication.

Example internal Remote WebDriver URL:

```txt
http://standalone-chrome.railway.internal:4444/wd/hub
```

If you access Selenium from outside Railway, use the public Selenium service URL instead.

Example public Remote WebDriver URL:

```txt
https://your-selenium-service.up.railway.app/wd/hub
```

This architecture keeps the Flask API lightweight while allowing Selenium to run as a dedicated browser automation service.

### How to Use

After deploying this template, Railway will create two services:

1. Flask REST API
2. Selenium Standalone Chrome

Open the generated Railway domain for the Flask service to test the starter API.

The Flask service connects to Selenium using a Remote WebDriver URL. In a Railway-to-Railway setup, use the private internal Railway URL for faster and private service communication.

Example environment variable for the Flask service:

```env
SELENIUM_REMOTE_URL=http://standalone-chrome.railway.internal:4444/wd/hub
```

If you run the Flask app locally on your computer, you cannot use the `.railway.internal` URL. Use the public Selenium Railway URL instead:

```env
SELENIUM_REMOTE_URL=https://your-selenium-service.up.railway.app/wd/hub
```

### Test the Scrape Endpoint

This template already includes a sample scrape endpoint in the Flask REST API service.

After deployment, test the Flask service using:

```txt
https://your-flask-service.up.railway.app/scrape
```

You can also test it with `curl`:

```bash
curl https://your-flask-service.up.railway.app/scrape
```

If the Flask service can connect to the Selenium Standalone Chrome service correctly, the endpoint should return a JSON response from the sample scraping task.

### How to Check Selenium Status

You can verify the Selenium service by opening its status endpoint.

Private Railway network:

```txt
http://standalone-chrome.railway.internal:4444/status
```

Public Railway URL:

```txt
https://your-selenium-service.up.railway.app/status
```

If the Selenium service is running correctly, it should return a JSON response showing the Selenium node status.

## Customization

If you want to customize the source code, use one of the workflows below.

### Via Railway CLI

Use this workflow if you want to edit the project locally and redeploy changes directly from your machine using Railway CLI.

1. Deploy the template.
2. Clone the repository from **Source Repo** or **Upstream Repo** in the Railway dashboard.
3. Enter the project directory:

```bash
cd your-project-directory
```

4. Link your local project directory to the deployed Railway project:

```bash
railway link
```

5. Check the linked project, environment, service, and repository information:

```bash
railway status
```

6. Edit the code locally.
7. Redeploy your local changes to Railway:

```bash
railway up
```

Railway will upload the current local directory and deploy it to the linked service.

### Via Git / GitHub

Use this workflow if you want to manage changes through GitHub and let Railway automatically redeploy after every push.

1. Deploy the template.
2. Open **Source Repo** or **Upstream Repo** from the Railway dashboard.
3. Fork the repository to your own GitHub account.
4. Clone your fork locally:

```bash
git clone your-fork-url
cd your-project-directory
```

5. Edit the code locally.
6. Commit and push your changes to your fork:

```bash
git add .
git commit -m "Customize Selenium Flask template"
git push origin main
```

7. In Railway, change the service **Source Repo** to your fork if Railway does not automatically create or link it.
8. After the service is connected to your fork, future pushes to the repository can trigger automatic redeployments.

## Common Use Cases

* Trigger automated browser tasks via REST API
* Scrape JavaScript-heavy websites
* Build internal scraping workers
* Run scheduled browser automation jobs
* Create lightweight data extraction APIs
* Test browser flows through remote Chrome sessions
* Integrate browser automation with n8n, cron jobs, webhooks, or backend systems

## Dependencies for Selenium with Flask Hosting

### Flask REST API Service

* Python
* Flask
* Selenium Python package
* Gunicorn or another Python WSGI server

### Selenium Service

* Selenium Standalone Chrome
* Headless Chrome
* Remote WebDriver endpoint

### Deployment Dependencies

This template uses two Railway services:

* Flask REST API service
* Selenium Standalone Chrome service

Recommended Selenium image:

```txt
selenium/standalone-chrome
```

Recommended Remote WebDriver endpoint:

```txt
http://standalone-chrome.railway.internal:4444/wd/hub
```

## Environment Variables

### Flask Service

```env
PORT=5000
SELENIUM_REMOTE_URL=http://standalone-chrome.railway.internal:4444/wd/hub
```

Use the public Selenium Railway URL if running Flask locally:

```env
SELENIUM_REMOTE_URL=https://your-selenium-service.up.railway.app/wd/hub
```

### Selenium Standalone Chrome Service

```env
PORT=4444
START_XVFB=true
SE_SCREEN_WIDTH=1920
SE_SCREEN_HEIGHT=1080
SE_SESSION_TIMEOUT=300
SE_NODE_CHROME_ARGS="--disable-dev-shm-usage --no-sandbox --disable-gpu --disable-extensions --disable-infobars --window-size=1920,1080 --headless=new --remote-allow-origins=*"
SE_NODE_MAX_SESSIONS=4
SE_NODE_SESSION_TIMEOUT=300
SE_NODE_OVERRIDE_MAX_SESSIONS=true
```

## Implementation Details

The Flask service connects to Selenium using Remote WebDriver. The remote URL is configured through the `SELENIUM_REMOTE_URL` environment variable.

Recommended Railway internal URL:

```txt
http://standalone-chrome.railway.internal:4444/wd/hub
```

For each scraping request, the Flask API should create a remote Selenium browser session, run the automation logic, close the browser session, and return a JSON response.

A good request lifecycle is:

1. Receive HTTP request in Flask.
2. Create remote Selenium browser session.
3. Open target page.
4. Extract required data.
5. Close the browser session.
6. Return JSON response.

Keep browser sessions short-lived and always close them after each request to avoid memory buildup or stuck Chrome sessions.

## Private vs Public URL

Use Railway private networking when the Flask service and Selenium service are deployed inside the same Railway project.

Private Railway URL:

```txt
http://standalone-chrome.railway.internal:4444/wd/hub
```

Use the public Selenium Railway URL when connecting from your local machine or from outside Railway.

Public Railway URL:

```txt
https://your-selenium-service.up.railway.app/wd/hub
```

The `.railway.internal` domain is only reachable from services running inside Railway. It is not accessible from your local computer.

## Why Deploy Selenium with Flask on Railway?

Railway is a singular platform to deploy your infrastructure stack. Railway will host your infrastructure so you do not have to deal with complex server configuration, while still allowing you to scale services vertically and horizontally.

By deploying Selenium with Flask on Railway, you get a clean two-service architecture for browser automation. The Flask API stays lightweight, while Selenium runs separately as a dedicated remote browser service.

This makes the template practical for scraping APIs, automation workers, internal tools, webhook-based browser tasks, and integrations with platforms like n8n or other backend systems.

## Similar templates

- [open-excalidraw](https://railway.com/deploy/open-excalidraw) — Self-hostable collaborative drawing built on Excalidraw
- [caring-vibrancy](https://railway.com/deploy/caring-vibrancy) — Deploy and Host caring-vibrancy with Railway
- [Appsmith](https://railway.com/deploy/appsmith-1) — Low-code platform for internal tools, dashboards, and admin panels.

Open this page in a browser: https://railway.com/deploy/selenium-flask
