Port 3001 — The Secondary Dev Port
Nobody chooses port 3001 intentionally — it's where you end up when port 3000 is already occupied. This is one of the most common situations in modern full-stack JavaScript development: the React frontend runs on port 3000, and the Express or Node.js API needs somewhere to go. Port 3001 is the next available option and has become an informal convention for the backend in React + API projects.
The Classic React + Express Setup
The most common reason to encounter port 3001 is the canonical full-stack development pattern:
# Terminal 1 — React frontend (Create React App / Vite)
npm start # Starts on localhost:3000
# Terminal 2 — Express API backend
node server.js # Starts on localhost:3001
The React app makes API calls to http://localhost:3001/api/.... In production, a single domain serves both — but locally they run on separate ports and processes.
Create React App — Automatic Port Reassignment
Create React App (CRA) detects port conflicts and offers to move automatically. When you run npm start and port 3000 is taken:
Something is already running on port 3000.
Would you like to run the app on another port instead? (Y/n)
Press Y and CRA starts on 3001 (or 3002, 3003... whichever is free). Vite behaves similarly, though it scans upward from its configured port without prompting. Next.js increments by 1 automatically.
Configuring a Fixed Port 3001
# Node.js / Express — hardcode the port
const PORT = process.env.PORT || 3001;
app.listen(PORT, () => console.log(`API running on :${PORT}`));
# Create React App — set in .env file
PORT=3001
# Vite — in vite.config.js
export default {
server: { port: 3001 }
}
# Next.js — start command
next dev -p 3001
# nodemon with specific port
nodemon --exec "PORT=3001 node server.js"
CRA Proxy — Connecting Frontend to Backend
When React on 3000 makes fetch requests to an Express API on 3001, you hit CORS issues in development. Create React App's built-in proxy solves this — add to package.json:
{
"proxy": "http://localhost:3001"
}
Now fetch('/api/users') in React automatically proxies to http://localhost:3001/api/users. In production, your API and frontend are on the same domain, so no proxy is needed.
For Vite, configure the proxy in vite.config.js:
export default {
server: {
port: 3000,
proxy: {
'/api': 'http://localhost:3001'
}
}
}
Other Apps on Port 3001
| App | Context |
|---|---|
| Gitea | Self-hosted Git service — sometimes configured on 3001 if 3000 is taken by Grafana |
| React Native Metro bundler (alt) | Metro tries 8081 by default; React dev server fallback to 3001 can appear during RN web development |
| n8n | Workflow automation tool, sometimes configured on 3001 in self-hosted setups |
| Custom APIs | Any Node/Deno/Bun backend server in a project where 3000 is the frontend |
Troubleshooting
| Problem | Fix |
|---|---|
| CORS error when React (3000) calls API (3001) | Add CRA proxy ("proxy": "http://localhost:3001" in package.json) or add CORS middleware to Express: app.use(cors()) |
| API starts on 3001 but React can't reach it | CRA proxy only works for the same-origin fetch calls — use /api/path not http://localhost:3001/api/path |
| Find what's using 3001 | lsof -i :3001 (Mac/Linux) | netstat -ano | findstr :3001 (Windows) |