When FreqUI does not load or a Freqtrade REST API request fails, the cause is usually one of four things: the API server is disabled, it is bound to the wrong interface, Docker is not publishing port 8080, or the client is using the wrong URL.
Start with the public health endpoint:
curl http://127.0.0.1:8080/api/v1/ping
A working API returns:
{"status":"pong"}
If that request fails, work through the checks below in order. Do not solve the problem by exposing port 8080 to the public internet. The Freqtrade API can control the bot and should remain behind localhost, an SSH tunnel, or a VPN.
Quick Diagnosis by Error
| Symptom | Most likely cause | First check |
|---|---|---|
Connection refused | Nothing is listening on that IP and port | API enabled, process running, bind address |
| Request times out | Firewall, routing, or incorrect host | Docker mapping, VPS firewall, tunnel |
{"detail":"Not Found"} | Incorrect path | Use /api/v1/ping |
401 Unauthorized | Protected endpoint needs credentials | Username, password, token flow |
| Browser shows a CORS error | Frontend and API use different origins | Exact CORS_origins value |
| Local curl works, remote browser fails | API is intentionally bound to localhost | Use an SSH tunnel or VPN |
| FreqUI opens but exchange data fails | Exchange connectivity is the problem | Proxy, DNS, clock, API credentials |
This table helps separate an API listener problem from an exchange connection problem. They occur in different parts of the stack and require different fixes.
Step 1: Enable the API Server
Add an api_server section to the configuration file that the running bot actually loads:
{
"api_server": {
"enabled": true,
"listen_ip_address": "127.0.0.1",
"listen_port": 8080,
"verbosity": "error",
"enable_openapi": false,
"jwt_secret_key": "replace-with-a-random-secret-at-least-32-characters",
"CORS_origins": [],
"username": "Freqtrader",
"password": "replace-with-a-strong-unique-password",
"ws_token": "replace-with-a-random-websocket-token"
}
}
Restart Freqtrade after changing the configuration. Then test:
curl http://127.0.0.1:8080/api/v1/ping
If Freqtrade starts with more than one config file, later files and environment variables can override earlier values. Use the same --config arguments for both testing and normal operation.
Step 2: Use the Correct Bind Address
The correct listen_ip_address depends on where Freqtrade runs.
Local Installation
Use:
"listen_ip_address": "127.0.0.1"
This accepts connections from the same machine only. It is the safest default.
Docker Container
Inside a container, 127.0.0.1 means the container itself. Docker cannot forward a host connection to a service that only accepts loopback traffic inside the container.
Use:
"listen_ip_address": "0.0.0.0"
Then restrict exposure with the host-side port mapping:
services:
freqtrade:
ports:
- "127.0.0.1:8080:8080"
This combination has two distinct jobs:
0.0.0.0lets the service receive traffic arriving through the container network.127.0.0.1:8080:8080publishes the port only on the Docker host's loopback interface.
Avoid a bare mapping such as "8080:8080" on an internet-facing server. It may make the API reachable from outside the machine.
Step 3: Confirm the Running Process Uses Your Config
Editing the right-looking file is not enough if the container or service loads a different path.
For Docker Compose, inspect the effective service and logs:
docker compose ps
docker compose logs --tail=100 freqtrade
Check the command and mounted volume in docker-compose.yml:
services:
freqtrade:
volumes:
- "./user_data:/freqtrade/user_data"
command: >
trade
--config /freqtrade/user_data/config.json
--strategy SampleStrategy
If your service has a different name, replace freqtrade in the log command.
For a script or virtual environment installation, start the bot with the intended file explicitly:
freqtrade trade \
--config user_data/config.json \
--strategy SampleStrategy
Look for configuration validation errors or an Address already in use message. A malformed config may prevent the API from starting even if the trading process appears to launch.
Step 4: Test from Each Network Layer
Testing from the right location reveals where connectivity stops.
Test on the Host
curl -v http://127.0.0.1:8080/api/v1/ping
Test Inside the Container
docker compose exec freqtrade \
curl -s http://127.0.0.1:8080/api/v1/ping
If the request works inside the container but not on the host, inspect the bind address and Docker port mapping.
Check Whether the Port Is Listening
On Linux:
ss -ltnp | grep 8080
Expected local-only Docker output normally includes a listener on 127.0.0.1:8080. If there is no listener, the API did not start or the port was not published.
Step 5: Use the Correct URL
The health-check URL is:
http://127.0.0.1:8080/api/v1/ping
Common URL mistakes include:
- Opening
/api/v1without an endpoint. - Using
https://when no reverse proxy provides TLS. - Using
localhostfrom another container and expecting it to reach Freqtrade. - Using the public VPS IP while the service is correctly bound to localhost.
- Sending a protected request without authentication.
Within a Compose network, another container should normally use the Freqtrade service name:
http://freqtrade:8080/api/v1/ping
The exact hostname is the Compose service name, not automatically the container name or localhost.
Step 6: Fix FreqUI CORS Errors
CORS matters when the browser loads FreqUI from an origin different from the API origin. An origin consists of the scheme, hostname, and port.
For a UI served from https://trading.example.com, configure:
{
"api_server": {
"CORS_origins": [
"https://trading.example.com"
]
}
}
Do not add a trailing slash:
Correct: https://trading.example.com
Incorrect: https://trading.example.com/
Do not use * with authenticated browser requests. Allow only the exact trusted origins that need access.
A CORS error is a browser policy error. If curl cannot connect at all, fix the listener or network path before changing CORS.
Step 7: Access FreqUI on a VPS Safely
The recommended pattern is to leave Freqtrade on localhost and create an SSH tunnel from your computer:
ssh -L 8080:127.0.0.1:8080 user@your-server
Keep the SSH session open, then visit:
http://127.0.0.1:8080
Traffic travels through the encrypted SSH connection, while port 8080 remains closed to the public internet.
If local port 8080 is already occupied, use a different local port:
ssh -L 18080:127.0.0.1:8080 user@your-server
Then open:
http://127.0.0.1:18080
A private VPN such as WireGuard is another suitable option. A reverse proxy can add HTTPS, but it does not make unrestricted public API exposure safe by itself.
Step 8: Distinguish Trade Mode from Webserver Mode
Running:
freqtrade trade
starts the trading or dry-run process. When the API server is enabled, FreqUI is available through the configured API port.
Running:
freqtrade webserver
starts the separate webserver workflow used for tasks such as strategy development and backtesting. Do not leave the command set to webserver when you expect the bot to trade.
For a one-off Docker webserver session, the port must be published explicitly if it is not already part of the service configuration:
docker compose run --rm \
-p 127.0.0.1:8080:8080 \
freqtrade webserver
When the API Works but the Exchange Does Not
If /api/v1/ping returns pong and FreqUI loads, the API server is functioning. Errors while loading markets, candles, or balances point elsewhere.
Check:
- Exchange API credentials and permissions
- DNS resolution
- System clock synchronization
- Exchange availability or rate limits
- Proxy configuration passed to CCXT
For a proxy-specific failure, follow the Freqtrade proxy troubleshooting guide.
Security Checklist
Before considering the issue resolved:
- Keep the host binding on
127.0.0.1whenever possible. - Use a unique password and a random JWT secret of at least 32 characters.
- Use a random WebSocket token.
- Do not commit secrets to Git.
- Prefer an SSH tunnel or VPN for remote access.
- Keep Freqtrade updated for current exchange compatibility and security fixes.
- Verify from an external network that port
8080is not publicly reachable.
Frequently Asked Questions
Why does FreqUI show a blank page?
Check the browser console and the Freqtrade logs. A failed API request, incorrect base URL, CORS mismatch, or incompatible cached UI assets can all produce a blank interface. First confirm that /api/v1/ping returns pong.
Why does localhost:8080 fail from another container?
Each container has its own loopback interface. Use the Compose service name, such as http://freqtrade:8080, and make sure both services share a Docker network.
Why does the API work inside Docker but not on the host?
The API may be bound to 127.0.0.1 inside the container, or Compose may not publish the port. Bind to 0.0.0.0 inside the container and publish it as 127.0.0.1:8080:8080 on the host.
Is it safe to open port 8080 in the VPS firewall?
Public exposure is not recommended. The API can perform sensitive bot actions. Use an SSH tunnel or a VPN instead.
Why do protected endpoints return 401 while /ping works?
The ping endpoint is public so it can report readiness. Other endpoints require the configured credentials or an access token.
Final Checklist
A secure working setup should satisfy all of these conditions:
api_server.enabledistrue.- Local installs bind to
127.0.0.1. - Docker installs bind to
0.0.0.0inside the container. - Docker publishes
127.0.0.1:8080:8080on the host. /api/v1/pingreturns{"status":"pong"}.- CORS contains only exact trusted origins when cross-origin access is required.
- Remote access uses an SSH tunnel or VPN.
Official references: