Geonode logo
Website and server errors

How to Fix Cloudflare Error Code 1003 (Direct IP Access Not Allowed)

Four checks, then the fix for your case, with cURL, Python and Node.js code for scripts.

Updated

TL;DR

Error code 1003 means Cloudflare refused a request sent straight to one of its IP addresses, with no website named in it. Use the domain name instead of the IP, in the browser and in any script.

What error 1003 looks like

Every http:// request we sent to a Cloudflare IP got plain text.

WhereWhat you see
Browser, http:// plus a Cloudflare IPerror code: 1003
curl http:// to the IP, default headersHTTP/1.1 403 Forbidden / Server: cloudflare / error code: 1003
macOS curl, https:// to some Cloudflare IPscurl: (60) SSL: no alternative certificate subject name matches target ipv4 address '104.16.2.189'
macOS curl, https:// to other Cloudflare IPscurl: (35) / sslv3 alert handshake failure
curl -k https:// to an IP that sends a certificateHTTP/2 403 / 403 Forbidden / cloudflare

Why this happens

Many websites share each Cloudflare IP, so your request must name the one you want.

Browsers and scripts copy the URL's host into the Host header, so a URL with an IP names no site. A DNS lookup of a site Cloudflare proxies returns a Cloudflare IP, so pasting that result gives 1003.

Diagnose your 1003 first

Each check shows where the IP entered your request, so you know which fix below applies.

  • Look at the address bar; if it shows digits such as 104.16.2.189 where the site's name should be, you opened an IP.

  • Compare the IP with the ranges at cloudflare.com/ips; if it falls inside one, the IP belongs to Cloudflare, not to the site's own server.

  • Run curl -v with your URL and headers; if the > Host: line shows digits, an IP is going out as the site name.

  • Search code and nginx config for proxy_pass, Host headers and URLs built from DNS lookups; an IP in any can go out as the host.

Solutions ranked by effectiveness

In a browser, the first card is enough; the second is for scripts and nginx, the third for site owners.

  1. Most common fix

    Open the site by its domain name

    Applies when you typed, pasted, bookmarked or followed a link to an IP address. Put the site's name in its place.

    1. In the address bar, replace the IP with the domain name, such as shop.example.com.

    2. If you need the name, check the email, link or app that gave the IP.

    3. Update the bookmark, start page or shortcut that still opens the IP.

  2. For developers

    Send the hostname, not a Cloudflare IP

    Applies to scripts and nginx. Put the hostname in the URL or in proxy_pass; if your code resolves DNS itself, connect to that IP but keep the name in Host and SNI.

    # The fix: put the site's name in the URL, not its IP
    curl -sS -o /dev/null -w "%{http_code} by name\n" https://example.com/
    
    # Resolving DNS yourself: connect to the IP, keep the name in Host and SNI
    IP=$(dig +short example.com | grep -m1 -E '^[0-9.]+$')
    curl -sS -o /dev/null -w "%{http_code} from %{remote_ip}\n" \
      --resolve "example.com:443:$IP" https://example.com/
  3. Site owners

    Check your zone status and DNS records

    Applies when people report 1003 while trying to reach your site. Their request named a Cloudflare IP, so confirm your domain works by name and keep IPs out of what you publish.

    1. In the Cloudflare dashboard, check that the domain's status is Active, not Pending or Moved.

    2. Point each A record at your origin server's IP, never at a Cloudflare IP.

    3. Swap IPs for the hostname in your links, monitors and webhooks.

    4. Do not offer your origin server's IP as a workaround; requests to it skip Cloudflare.

Stop the 1003 from coming back

For scripts, monitors and servers that call Cloudflare sites every day.

  1. Store sites by name and resolve at run time, since Cloudflare can change the IP behind a proxied record.

  2. Validate target lists before a run, and refuse entries whose host part is an IP address.

  3. Log each 1003 as a config bug and skip retries; it is not among Cloudflare's six retryable 1xxx codes.

  4. Behind nginx, turn proxy_ssl_server_name on for HTTPS upstreams; it is off by default, so no SNI is sent.

Proxy hostnames that follow IP changesUse a hostname such as proxy.geonode.io, and DNS keeps up when proxy servers change IPs.
Try residential proxies

Related errors

Learn more

FAQ

It is Cloudflare's Direct IP access not allowed error. The URL held a Cloudflare IP where the site's name belongs, so Cloudflare could not tell which site you wanted and answered HTTP 403.

Put the website's domain name wherever the IP appears: the address bar, a bookmark, a script's URL or a Host header. Cloudflare's docs give the same resolution.

An http:// URL with a Cloudflare IP makes curl send that IP as the host. In our https:// tests it failed sooner, with curl error 35 or 60, since TLS server names cannot be IPs.

No. It depends on the address in your URL, not on who sends the request, while Cloudflare's IP blocks, country blocks and firewall rules return other codes, such as 1005 to 1008.

Only if what you send through it names a Cloudflare IP. For https:// sites the proxy relays a tunnel to the host your client names, so writing the proxy's own address as an IP is harmless.

With 1003 the request named a Cloudflare IP instead of a site. With 1001 it named a site whose domain is not on Cloudflare, or whose CNAME target does not resolve.

Keep proxy credentials out of scripts

Whitelist the IP your scripts run from, and they skip the username and password.