---
title: "Deploy Cobalt | (Just Updated) Media Downloader No Stranger Can Use on Your Bill"
description: "Self-hosted media downloader: API-key auth enforced, YouTube poToken server"
category: "Bots"
url: https://railway.com/deploy/cobalt-or-just-updated-media-downloader-
---

# Deploy Cobalt | (Just Updated) Media Downloader No Stranger Can Use on Your Bill

Self-hosted media downloader: API-key auth enforced, YouTube poToken server

**[Deploy Cobalt | (Just Updated) Media Downloader No Stranger Can Use on Your Bill on Railway](https://railway.com/template/cobalt-or-just-updated-media-downloader-)**

- **Creator:** SuperSlowSloth
- **Category:** Bots
- **Total deploys:** 1

## Template content

### pot

- **Image:** brainicism/bgutil-ytdlp-pot-provider:1.3.1-node

### cobalt

- **Image:** ghcr.io/imputnet/cobalt:11.7.1
- **Start command:** `/bin/sh -c 'set -e; : ${COBALT_API_KEY:?COBALT_API_KEY_is_required}; d=$HOME; [ -w $d ] || d=/tmp; printf {\\042%s\\042:{\\042name\\042:\\042owner\\042,\\042limit\\042:\\042unlimited\\042}} $COBALT_API_KEY > $d/keys.json; export API_KEY_URL=file://$d/keys.json API_AUTH_REQUIRED=1 API_PORT=$PORT API_LISTEN_ADDRESS=0.0.0.0; echo [railway] api key file at $d/keys.json; exec node src/cobalt'`
- **Health check:** /
- **Public domain:** Yes

## Documentation

# Deploy and Host Cobalt on Railway

Cobalt is an open-source media downloader from [imput](https://github.com/imputnet/cobalt): give
it a link from YouTube, TikTok, Instagram, X, Reddit, SoundCloud, Twitch clips, Vimeo, Bluesky and
about twenty other sites, and it returns a clean file — no ads, no trackers, no remuxing service in
the middle. This template deploys the Cobalt **API** (the part that does the work and that apps,
scripts and the public cobalt frontend talk to), with the API key already generated and enforced.

## About Hosting Cobalt

Cobalt's API is a small Node service that resolves a media URL and then either hands back a direct
link or tunnels the stream through itself, remuxing on the fly when the site serves video and audio
separately. That makes it bandwidth- and CPU-resident rather than storage-heavy: there is no
database, no volume, and nothing to migrate — but every request costs the instance real egress. The
consequence people miss when self-hosting is that an instance with no authentication is a public
service, and the bill is the deployer's.

This deployment pins Cobalt 11.7.1, turns authentication **on** (`API_AUTH_REQUIRED`), generates a
UUID API key for you at deploy time, writes the key file the API expects, and runs a
`poToken` provider alongside the API so that YouTube requests keep working if Google starts
challenging the datacenter address your instance runs on.

## Why Deploy Cobalt on Railway

Railway gives the API a public HTTPS domain, restarts it on failure, and bills the bandwidth it
actually uses — which suits a service whose entire cost profile is "outbound traffic when someone
downloads something". There is no state to persist, so a redeploy is free of risk, and the two
services in this template talk over Railway's private network rather than the public internet.

## Common Use Cases

1. A private backend for a personal downloader page or bot, with a key only you hold.
2. An archiving script that saves your own posts and uploads before a platform removes them.
3. A step in an automation (n8n, Make, a cron job) that needs the raw media file behind a link.
4. A self-hosted API for the official cobalt web frontend, instead of using someone else's instance.

## Dependencies for Cobalt Hosting

* The official Cobalt API image, pinned: `ghcr.io/imputnet/cobalt:11.7.1`.
* A `poToken` provider for YouTube: `brainicism/bgutil-ytdlp-pot-provider:1.3.1-node`, deployed as
  a private service the API reaches over Railway's internal network.

### Deployment Dependencies

* Cobalt upstream: https://github.com/imputnet/cobalt
* API environment variable reference: https://github.com/imputnet/cobalt/blob/main/docs/api-env-variables.md
* poToken provider: https://github.com/Brainicism/bgutil-ytdlp-pot-provider

### Implementation Details

Authentication is on by default. The template generates `COBALT_API_KEY` as a UUID and writes it
into the key file Cobalt reads (`API_KEY_URL`), so nothing is left for you to configure. Requests
must carry that key with the **`Api-Key`** scheme — not `Bearer`, which Cobalt rejects:

```
curl -X POST https://your-instance.up.railway.app/ \
  -H 'Accept: application/json' \
  -H 'Content-Type: application/json' \
  -H 'Authorization: Api-Key ' \
  -d '{"url": "https://www.youtube.com/watch?v=dQw4w9WgXcQ", "videoQuality": "1080"}'
```

Without the header the API answers `400 {"error":{"code":"error.api.auth.key.missing"}}`.

The API honours the port Railway injects, and the service refuses to start if the key variable is
ever emptied, so a misconfigured instance fails loudly instead of coming up unprotected.

## Why this template

* **The API is not open to the world.** Two of the templates in this category publish a variable
  named `API_KEY` — a name that appears nowhere in Cobalt's source, which reads only `API_KEY_URL`
  and `API_AUTH_REQUIRED`. Deployed from those templates, an anonymous `POST /` with no headers at
  all returns `200 {"status":"tunnel", ...}` and streams the file, on the deployer's bandwidth. One
  of them documents an `Authorization: Bearer ` header that the API ignores. Here the same
  anonymous request returns `400 error.api.auth.key.missing`, and the generated key works.
* **YouTube keeps working when the IP gets challenged.** Cobalt asks its session server for a
  `poToken` by `POST /get_pot`, which is the API of the bgutil provider deployed here — Cobalt's
  own docs still point at `yt-session-generator`, whose webserver serves `/token` and answers that
  call `404 Not Found`. No other template in this category deploys a token provider at all,
  including the one whose name promises fixed YouTube downloads.
* **The version is pinned.** Everyone else runs `:latest` on both images.
* **Nothing to fill in.** The deploy form asks for nothing: the key is generated, the public URL is
  wired to `API_URL`, and the provider address is wired over private networking.

## Notes and limits

* This deploys the **API**, not the cobalt web page. Point the official frontend or your own client
  at the instance URL, with the key.
* Downloading YouTube from a datacenter address is challenged by Google intermittently. The token
  provider is what keeps that working; measured on the day this template was published, a stock
  instance without one still resolved every test video, so treat the provider as insurance rather
  than as a fix for a failure you are seeing today.
* Cobalt keeps no library and no history — files stream through and are gone.


## Similar templates

- [Telegram JavaScript Bot](https://railway.com/deploy/5lRkWa) — A template for Telegram bot in JavaScript using grammY
- [Cobalt Tools [Updated Aug ’26]](https://railway.com/deploy/cobalt) — Cobalt Tools [Aug ’26] (Media Downloader, Converter & Automation) Self Host
- [Telegram Gateway](https://railway.com/deploy/railway-telegram-gateway) — Multi-bot Telegram webhook gateway with real-time WebSocket event streaming

Open this page in a browser: https://railway.com/deploy/cobalt-or-just-updated-media-downloader-
