---
title: "Deploy Polymarket Bot [Updated Sep '26]"
description: "Polymarket Copy-Trading Bot — Self-Hosted | Buy & Sell with Auto Cashout"
category: "Bots"
url: https://railway.com/deploy/polymarket-bot
---

# Deploy Polymarket Bot [Updated Sep '26]

Polymarket Copy-Trading Bot — Self-Hosted | Buy & Sell with Auto Cashout

**[Deploy Polymarket Bot [Updated Sep '26] on Railway](https://railway.com/template/polymarket-bot)**

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

- **Creator:** shruistic
- **Category:** Bots

## Template content

### polymarket-bot https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRRhJDmjdIHCfIPN3UJqgVO7_naqmlkX1gHEeavn2pSpQ&s=10

- **Source:** https://github.com/shruti060701/polymarket-bot-railway

## Documentation

# Deploy and Host Polymarket Bot V2 on Railway

Polymarket Bot V2 is a TypeScript copy-trading bot for Polymarket — it watches selected trader wallets and mirrors their trades under your own spend limits, with optional auto-redeem once a market resolves. This template deploys a patched fork, verified live against both the actual crash the upstream reference has and the fix for it.

## About Hosting Polymarket Bot V2

The bot runs as a single always-on Node.js process: it polls Polymarket's activity feed for trades from wallets you specify, applies your copy strategy (percentage of size, fixed USD, or fixed shares) within hard daily-volume and per-position caps, and optionally redeems resolved positions automatically. Nothing about your wallet or credentials passes through a third-party operator — you provide your own Polymarket-linked private key, and the bot runs entirely under your control.

## Why Deploy Polymarket Bot V2 on Railway

The reference version of this template on Railway's marketplace currently sits at 33% health, noticeably worse than a typical config-only issue. Digging into why led to an actual bug in the bot's own startup code, not a Railway networking problem.

## This Template's Root Cause and Fix

In the upstream source (`src/index.ts`), `main()` wraps only the call to `loadConfig()` in a try/catch, and only handles its own `ConfigError` type gracefully — everything else re-throws and hits a bottom-level `main().catch()` that calls `process.exit(1)`. The problem: `new Wallet(PRIVATE_KEY)` gets called twice outside any graceful handling — once inside `loadConfig()` itself (to derive a fallback profile address), and again inside `ClobService.init()`, which runs entirely outside the try/catch block. Either call throws a plain `ethers` error, not a `ConfigError`, the moment `PRIVATE_KEY` isn't a valid 32-byte hex string.

That's a very reachable failure mode here specifically, because `PRIVATE_KEY` is a long hex secret most users copy-paste from Polymarket's Magic key-reveal page (`reveal.magic.link/polymarket`) — a stray leading space, a missing `0x`, or one dropped character is enough. Combine that with roughly twenty required fields total (private key, profile address, trader list, and — if auto-redeem is on — an RPC URL plus three separate Builder API credentials), and the odds that at least one field gets mistyped on a first deploy climb fast. With `restartPolicyMaxRetries: 10` and no graceful path for this specific error, a mistyped key means ten identical crashes and a deployment that shows FAILED.

The fix applied in this fork is a small, surgical change to the bottom-level catch handler: instead of exiting on anything that isn't a `ConfigError`, it now treats every startup failure the same way — log it clearly, then idle:

```js
main().catch((err) => {
  const label = err instanceof ConfigError ? "config" : "startup";
  const message = err instanceof Error ? err.message : String(err);
  console.error(`[${label}] ${message}`);
  void idleLoop();
});
```

## Verified Live, Before and After

Both scenarios were deployed with the exact same deliberately malformed `PRIVATE_KEY` (`0x1234`, correct prefix, wrong length) and otherwise-valid surrounding values, so the comparison isolates the one variable:

- **Unpatched upstream code**: deployment status `CRASHED`. Logs show the stack trace originating at `new Wallet` inside both `loadConfig` and the `ClobService` path, ending in `process.exit(1)`, repeated across restart attempts.
- **This fork's patched code**: deployment status `SUCCESS`. Logs show `[startup] invalid private key (argument="privateKey", ..., code=INVALID_ARGUMENT, ...)` followed by `Fix configuration and restart the bot...` — the process stays up, waiting for a corrected redeploy, instead of crash-looping.

## Common Use Cases

- **Copy-trading a single high-signal trader**: mirror one wallet's positions with hard spend limits
- **Diversifying across multiple traders**: mirror several wallets at a fixed percentage each
- **Running a self-custodied bot**: your own private key, your own server, no third-party operator holding your credentials or your funds
- **Auto-redeeming resolved positions**: optional, requires a Polygon RPC endpoint and Polymarket Builder credentials

## Dependencies for Polymarket Bot V2 Hosting

Just one service — no database, no cache. A persistent volume at `/data` stores `state.json`, tracking which trades and redemptions have already been processed so a restart doesn't re-execute them.

### Implementation Details

This template builds from source (Node 22 via Railpack) rather than a prebuilt image, since the bot has no published Docker image. `RAILPACK_NODE_VERSION=22` is set explicitly — a couple of dependencies warn or fail to install below Node 20.10, and the reference build runs Node 18 by default without it.

## Why Self-Hosting Matters Here Specifically

Custodial copy-trading services — where you hand a third party your credentials or funds and let them execute trades on your behalf — carry a real, documented risk beyond the usual "trust a company with your data" concern: a widely reported supply-chain attack against one large custodial copy-trading operator resulted in a roughly $230,000 loss in a single incident. Self-hosting removes that specific failure mode entirely, since your private key never leaves infrastructure you control, and no third party ever holds custody of your funds.

## How Polymarket Bot V2 Compares to Commercial Alternatives

Commercial Polymarket bot products generally charge either a flat subscription (roughly $29–$50/month for signal or copy-trading features from various providers) or a one-time license fee in a similar range, and several are custodial by design. Self-hosting this template has no subscription or license cost at all — only your Railway infrastructure bill — and keeps custody of your funds and your private key on infrastructure you run yourself throughout.

## Getting Started

Deploy the template with `DRY_RUN=true` (the default) first, and provide your real `PRIVATE_KEY`, `PROFILE_ADDRESS`, and `COPY_TRADERS`. Check the deploy logs: a clean run polls silently; a misconfigured one now logs a clear `[startup]` or `[config]` error and idles instead of crashing. Once you've confirmed the logs look right, set `DRY_RUN=false` to let it place real orders.

## Frequently Asked Questions

### Why did the reference template end up with poor health?
A code bug: any startup failure other than a `ConfigError` — most commonly an invalid `PRIVATE_KEY` — crashes the process uncaught instead of failing gracefully. This template patches that specific handler.

### Is this template custodial?
No. You provide your own private key directly to your own deployment; nothing routes through a third-party operator or holds your funds.

### What happens if I deploy without filling in real credentials?
The bot logs a clear `[config]` or `[startup]` error explaining exactly what's wrong, then idles — it no longer crashes the deployment. Fix the variable and redeploy.

### Does this bot need a database?
No — just the one persistent volume at `/data` for its local state file.

### Is DRY_RUN safe to leave on indefinitely?
Yes. With `DRY_RUN=true`, the bot simulates orders without ever sending them, which is a reasonable way to confirm your trader list and limits look right before risking real funds.

## Similar templates

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

Open this page in a browser: https://railway.com/deploy/polymarket-bot
