ERCOT engineering guide · Operations
Why an ERCOT API collector can work locally but fail in the cloud
The same request, the same credentials, a different answer. A troubleshooting method for 403s after deployment, without guessing and without working around ERCOT's security controls.
You finish an ERCOT collector locally. Authentication works, the endpoint responds, data arrives.
You deploy the same application to a cloud environment and receive a 403.
That doesn't automatically mean your Python code or your credentials changed. Moving from a laptop to production also changes your network origin, your outbound IP, your routing and often your HTTP client stack — and any of those can matter to the security systems in front of an API.
Where this guide sits in the pipeline
- Source
- Fetch
- Raw copy
- Validate
- Verify completeness
- Normalize
- Promote
- Client system
What developers have reported
- March 2025 (Discussion #85). A user received 403s calling ERCOT from Western Europe. ERCOT staff replied that, as a security precaution, specific regions are blocked from
*.ercot.com, and later that the geo-region restrictions would remain in place. - June 2025 (Discussion #96). A user received a 403 through an office VPN whose exit address was in the US. ERCOT staff reported that their security team was not blocking that IP; the cause they identified was that the client did not support HTTP/2. A later follow-up in the same thread, asking about 403s from cloud static IPs, had no reply when we reviewed it.
- March 2026 (Discussion #136). A user received a 403 with a web-application-firewall challenge page when calling the LMP endpoint from a cloud-hosted worker, while the same request returned 200 from their local machine and sign-in succeeded. They asked about IP allowlisting. ERCOT staff replied that geo-restrictions are in place and that individual system whitelisting is not supported at this time.
Developers have reported cases where the same ERCOT request behaved differently from cloud infrastructure than from a local environment. These reports don't show that ERCOT blocks cloud servers as a rule. They do show that a 403 after deployment can come from network origin, from how the client connects, or from security filtering — and that the answer comes from testing, not guessing.
Prove the difference
Run the smallest equivalent request from both environments: the same endpoint and parameters, the same credentials (each read from that environment's secret store), the same library versions.
- Local succeeds, cloud fails: the difference is the environment, not the code.
- Both fail: look at the request, the credentials, or ERCOT's side first.
- Sign-in succeeds in both but data fails in the cloud: the problem is between the cloud environment and the data API.
Log useful response metadata
When a request is denied, capture enough to diagnose it — without logging secrets:
- status code and timestamp
- endpoint and query parameters
- a request or correlation ID, if the response includes one
- a short allowlist of safe response headers
- the first few hundred characters of the error body
Never log the password, the subscription key or the bearer token.
import requests
SAFE_HEADERS = {"content-type", "date", "server", "retry-after", "x-request-id"}
def describe_failure(response: requests.Response) -> dict:
return {
"status": response.status_code,
"url": response.request.url, # API URLs carry no secrets; the key and token are headers
"headers": {k: v for k, v in response.headers.items() if k.lower() in SAFE_HEADERS},
"body_start": response.text[:300],
}
The body is often the biggest clue. An HTML challenge page where you expected a JSON error means the request was stopped by a security layer before it reached the API itself.
Know your outbound IP
Your application's outbound address is often not your server's address. NAT gateways, load balancers, proxies and static-IP add-ons all decide what address ERCOT sees. Find the real egress IP from inside the running environment — not from the console — and check how it geolocates, which is what ERCOT staff suggested in Discussion #96. A proxy or egress service can put your traffic in a different place than your servers.
Know the deployment region
ERCOT staff have said that specific regions are blocked as a security precaution (Discussion #85) and that geo-restrictions are in place (Discussion #136). ERCOT hasn't published which regions, and we won't guess. If your egress geolocates somewhere you didn't expect, rule that out first. Run the collector from infrastructure whose egress you control and can verify, and ask ERCOT directly if you're unsure whether a location is permitted.
Check how the client connects
In the June 2025 case the issue was the client, not the address: ERCOT's security team identified a client that didn't support HTTP/2. That doesn't make HTTP/2 a universal requirement — ERCOT's own Python starter sample uses requests, which speaks HTTP/1.1 — but differences between a laptop and a container image in TLS libraries, HTTP versions, proxies and default headers are worth comparing directly.
Separate authentication failure from network denial
Sign-in and data requests go to different hosts: the token comes from ERCOT's B2C sign-in service (ercotb2c.b2clogin.com) and data from api.ercot.com. Test them separately. In Discussion #136, sign-in succeeded while the data request was denied; in Discussion #124, sign-in kept working while data requests hung. A working token proves your credentials, not your network path to the data API.
Test production networking early
Make a real, small ERCOT request from the target environment in the first days of a project, not the day before launch. Networking and security questions can take a long time to answer, and you want to find a 403 while there's still time to change where the collector runs. Keep that request as a scheduled health check, so a change in either environment shows up as an alert rather than a gap.
Don't build unofficial workarounds
If ERCOT's security controls reject your deployment environment, don't try to get around them — rotating IP addresses, routing through third-party proxies to change your apparent location, or imitating a browser to pass a challenge page. Workarounds like these undermine controls that exist for a reason, break without warning, and put your access at risk. Work with ERCOT, or use an access path ERCOT officially supports. Surviving ERCOT API failures covers how a collector should behave when it gets a 403: stop and alert, not retry in a loop.
Practical takeaway
- Reproduce with the smallest equivalent request from both environments.
- Log status, safe headers and the start of the body — never secrets.
- Check the real egress IP and how it geolocates.
- Compare client stacks: HTTP version, TLS, proxies.
- Test sign-in and data access separately.
- Test from production networking early; never work around security controls.
Related ERCOT guides
Reliability
How to make an ERCOT data pipeline survive 400s, 429s, 500s and timeouts
An error taxonomy for ERCOT collectors: backoff with jitter, retry budgets, persisted state and quarantine.
Read the guideAPI
Getting started with the ERCOT Public API in Python
Registration, authentication, a first request, pagination, and the pieces a collector needs to run unattended.
Read the guideAPI
Building a reliable ERCOT API pipeline under rate limits
Why ERCOT API 429s appeared in March 2026, and how to collect in small, resumable windows without hardcoding limits.
Read the guideSources & further reading
ERCOT APIs, publication behavior and access policies can change. These sources were reviewed on September 21, 2026; verify current requirements against ERCOT's official documentation before implementing production systems. Discussion threads mix ERCOT staff replies with community reports, and the notes below say which is which.
- Discussion #85: 403 from outside the US? ERCOT staff replies, March 24 and 28, 2025. Marked answered.
- Discussion #96: 403 Forbidden IP from Chicago IP ERCOT staff replies, June 11 and 12, 2025. A later community follow-up was unanswered when reviewed.
- Discussion #136: 403 Imperva WAF block when calling the LMP API from a cloud server Community report, March 28, 2026; ERCOT staff reply, March 30, 2026. Not marked answered.
- Discussion #124: Public API requests timing out Community reports from January 26, 2026; ERCOT staff reply, January 27, 2026. Not marked answered.
- ERCOT Public API: registration and authentication Official ERCOT developer documentation.