---
title: "Deploy template-obscura"
description: "Obscura headless browser with private, authenticated CDP."
category: "Automation"
url: https://railway.com/deploy/template-obscura
---

# Deploy template-obscura

Obscura headless browser with private, authenticated CDP.

**[Deploy template-obscura on Railway](https://railway.com/template/template-obscura)**

Machine-readable deploy manifest (JSON, validated by TemplateCI): https://railway.com/deploy/template-obscura/manifest.json

- **Creator:** Life of Jer
- **Category:** Automation

## Template content

### obscura

- **Source:** https://github.com/lifeofjer/obscura

## Documentation

# Deploy and Host Obscura Headless Browser on Railway

## About Hosting Obscura

Deploy Obscura v0.2.6 with an authenticated Chrome DevTools Protocol endpoint for Puppeteer and Playwright. The image uses the official non-stealth release, runs as a non-root user, and downloads a checksum-verified release binary at build time.

## Why Deploy Obscura on Railway

Run an authenticated browser next to your workers over Railway private networking. Each deployment uses a pinned browser release and a readiness check.

## Common Use Cases

- Extract text and tables from JavaScript-rendered public pages.
- Verify that a public page renders expected content in an automated check.

## Dependencies for Obscura

### Deployment Dependencies

The template creates one service. A client in the same Railway environment can connect using Puppeteer or Playwright.

Set the required `OBSCURA_CDP_TOKEN` to a unique random secret when deploying. Generate one with `openssl rand -hex 32`.

## Connect on Railway

Use the private hostname from a service in the same Railway environment. Set `OBSCURA_HOST` to the browser service's private hostname and pass that service's `OBSCURA_CDP_TOKEN` to the client as a secret. Set `OBSCURA_PORT` to the browser port shown in its startup log. You can set `PORT=9222` on the browser service to choose a fixed port.

```js
import puppeteer from 'puppeteer-core';

const browser = await puppeteer.connect({
  browserWSEndpoint: `ws://${process.env.OBSCURA_HOST}:${process.env.OBSCURA_PORT}/devtools/browser`,
  headers: { Authorization: `Bearer ${process.env.OBSCURA_CDP_TOKEN}` },
});

try {
  console.log(await browser.version());
} finally {
  await browser.disconnect();
}
```

Railway checks `GET /healthz`. Browser discovery and WebSocket connections require the token. Keep the service on private networking and store the token as a service variable.

[Obscura documentation](https://docs.obscura.sh) · [Upstream release](https://github.com/h4ckf0r0day/obscura/releases/tag/v0.2.6)


## Similar templates

- [N8N Main + Worker](https://railway.com/deploy/n8n-main-worker) — Deploy and Host N8N with Inactive worker.
- [Evolution API with n8n](https://railway.com/deploy/evolution-api-with-n8n) — Automate WhatsApp workflows with Evolution API, n8n, and Postgres.
- [Postgres Backup](https://railway.com/deploy/postgres-s3-backups) — Cron-based PostgreSQL backup to bucket storage

Open this page in a browser: https://railway.com/deploy/template-obscura
