AWS CLI "Could not connect to the endpoint URL"? Fix It

Package aws-cli/2.37.3, bind-utils (dig), curl, nmap-ncat (nc) on RHEL 10.2
AWS Region ap-south-1 (Mumbai) for the examples. Many AWS CLI service endpoints are Regional, while some services also use global or special endpoints.
Lab environment Workstation with AWS CLI v2 and configured credentials — AWS CLI tutorial
Install AWS CLI on Ubuntu · Install AWS CLI on Debian
Privilege Valid AWS credentials for the API being tested; on EC2, a network path to the service endpoint (public subnet egress, NAT from a private subnet, or an appropriate VPC endpoint)
Scope Why the AWS CLI returns Could not connect to the endpoint URL or Failed to connect to proxy URL, how to read the hostname from the error, and how to separate DNS, TCP/TLS, proxy, and VPC egress problems from IAM permission errors. Covers Region defaults, --endpoint-url, corporate proxies, private subnets without egress, and PrivateLink private DNS gaps. Does not cover AccessDenied or Unable to locate credentials. AccessDenied means the request reached AWS and authorization failed. Unable to locate credentials means the CLI could not find credentials needed to sign the request, so the request was not sent.
Related guides AWS CLI Tutorial
Unable to locate credentials
InvalidClientTokenId
AccessDenied despite AdministratorAccess
AWS Tutorial
Short on time?Beta Get the gist of this 14-minute read in seconds, then ask follow-up questions

Could not connect to the endpoint URL means the AWS CLI could not establish a usable connection to the service endpoint shown in the error. The request did not reach the AWS service API, so start with endpoint selection, DNS, proxy, firewall, and network routing—not IAM permissions.

An AWS service endpoint is the hostname the CLI connects to when it calls an AWS API. For example, an S3 request in Mumbai may use s3.ap-south-1.amazonaws.com. The CLI must first select the correct endpoint, resolve its DNS name, and establish an HTTPS connection before AWS can process the API request.

The examples use AWS CLI 2.37.3 on a Linux workstation with valid credentials. The same hostname, DNS, proxy, and egress checks apply from CI runners, bastion hosts, and private EC2 instances that call Regional endpoints such as s3.ap-south-1.amazonaws.com.

              aws s3 ls
                |
                v
   AWS CLI chooses the S3 endpoint
      s3.ap-south-1.amazonaws.com
                |
                v
   DNS resolves hostname to an IP?
                |
                v
 HTTPS connection to port 443 succeeds?
                |
       +--------+--------+
       |                 |
      yes                no
       |                 |
       v                 v
 AWS receives      Could not connect
 the API request  to the endpoint URL
       |
       v
 IAM authorization happens here

Endpoint selection means deciding which AWS hostname the CLI should call. Use this table to pick the first check:

Symptom Most likely area First check
URL contains typo or bad Region Endpoint selection aws configure list; inspect the URL in the error
DNS fails Resolver or VPC DNS dig or getent hosts on the hostname
DNS works; port 443 times out Routing, firewall, or NAT nc or curl --connect-timeout
Failed to connect to proxy URL Proxy env plus grep -i proxy
Works on laptop, fails on EC2 VPC egress or endpoints Route table, NAT, VPC endpoint
AccessDenied Not a connection problem IAM troubleshooting guides

Read the Endpoint from the Error

Start with the hostname shown in the error. Test that exact name with DNS and connectivity tools before changing IAM or credentials.

For example, forcing the CLI to use an unreachable endpoint reproduces the error:

bash
aws s3 ls --endpoint-url https://127.0.0.1:9
output
aws: [ERROR]: Could not connect to the endpoint URL: "https://127.0.0.1:9/"

The hostname 127.0.0.1 on port 9 is local and nothing listens there, so the connection is refused. That pattern also appears when a stale AWS_ENDPOINT_URL or config file points at a decommissioned load balancer.

If the proxy itself cannot be reached, the CLI reports the proxy URL instead:

bash
HTTPS_PROXY=http://127.0.0.1:9 aws s3 ls
output
aws: [ERROR]: Failed to connect to proxy URL: "http://127.0.0.1:9"

When the proxy line appears, fix HTTPS_PROXY / HTTP_PROXY first—the CLI never reached the AWS hostname.

Error substring Likely layer
Could not connect to the endpoint URL Wrong or unreachable service hostname, DNS failure, firewall block, or no route to the internet
Failed to connect to proxy URL HTTPS_PROXY, HTTP_PROXY, or NO_PROXY misconfiguration
Connection was closed before we received a valid response TLS or middlebox interference after TCP connected
AccessDenied Request reached AWS; check IAM (not this guide)
Unable to locate credentials No signing key; check profiles and env vars

Check Region and Service Name

The endpoint the CLI chooses depends on the AWS service and the effective Region (s3, ec2, sts, and so on). A valid but incorrect Region often results in a service-level redirect or a resource-not-found style problem rather than a connection failure. But a mistyped, unsupported, or invalid Region can make the CLI construct a hostname that does not exist, which produces Could not connect to the endpoint URL.

Confirm the Region the CLI will actually use—not only the value stored in the profile file:

bash
aws configure list
output
      Name                    Value             Type    Location
      ----                    -----             ----    --------
   profile                <not set>             None    None
access_key     ****************ABCD              env
secret_key     ****************WXYZ              env
    region               ap-south-1              env    AWS_REGION

The important part is the Type and Location columns. In this example, the Region comes from the AWS_REGION environment variable, so changing ~/.aws/config would not fix the problem until that environment variable is removed or changed.

Region precedence (highest wins):

   --region command-line option
                |
                | overrides
                v

            AWS_REGION
                |
                | overrides
                v

       AWS_DEFAULT_REGION
                |
                | overrides
                v

   profile configuration (~/.aws/config)

For Amazon S3 in ap-south-1, the Regional endpoint hostname is s3.ap-south-1.amazonaws.com. IAM and some other APIs use different endpoint patterns; the hostname in the error should match the service documentation for that API.

List endpoint-related environment variables in the same shell:

bash
env | grep -E '^AWS_(REGION|DEFAULT_REGION|ENDPOINT_URL)'

AWS_ENDPOINT_URL changes the endpoint used broadly by AWS CLI services, while a variable such as AWS_ENDPOINT_URL_S3 changes only S3. That means S3 can still be broken even when the global variable is empty.

bash
export AWS_ENDPOINT_URL_S3=http://127.0.0.1:4566

With only the S3 override set, list buckets to see which hostname the CLI uses:

bash
aws s3 ls

The CLI will try the custom S3 endpoint instead of AWS's normal Regional endpoint. Service-specific variables take precedence over the global AWS_ENDPOINT_URL for that service. A stale AWS_ENDPOINT_URL_S3 can remain even when AWS_ENDPOINT_URL is unset. The CLI can also read endpoint overrides from profile configuration in ~/.aws/config.

Checklist before DNS tests:

  • Effective Region from aws configure list matches the resources being accessed
  • No accidental --endpoint-url left from LocalStack, MinIO, or an old PrivateLink test
  • No stale AWS_ENDPOINT_URL or AWS_ENDPOINT_URL_<SERVICE> pointing at a retired host
  • Optional diagnostic when a custom endpoint override is suspected: run one command with AWS_IGNORE_CONFIGURED_ENDPOINT_URLS=true to ignore configured custom endpoint URLs. An explicit --endpoint-url still takes precedence
  • Bucket-specific calls use a bucket Region that matches the endpoint (wrong-Region bucket errors are usually HTTP redirects or signature errors, not connection refused)

Resolve the AWS Endpoint with DNS

If dig or getent hosts cannot resolve the hostname from the error, the CLI cannot connect either. getent hosts is often already available on RHEL without installing bind-utils.

For the valid Regional hostname:

bash
dig +short s3.ap-south-1.amazonaws.com
output
3.5.208.54
3.5.213.238
3.5.213.153

Multiple A records are normal for AWS service endpoints such as S3.

A deliberately invalid Regional hostname returns no answers:

bash
dig +short s3.not-a-real-region.amazonaws.com

With no DNS answers, the CLI fails when that hostname is forced through --endpoint-url:

bash
aws s3 ls --endpoint-url https://s3.not-a-real-region.amazonaws.com
output
aws: [ERROR]: Could not connect to the endpoint URL: "https://s3.not-a-real-region.amazonaws.com/"

On EC2 instances that use the AmazonProvidedDNS resolver (169.254.169.253), compare results from the instance with a workstation on the public internet. If public DNS resolves the name but the instance does not, check VPC DHCP options sets, custom resolver forwarders, and Route 53 Resolver rules before blaming the CLI.


Test TCP/TLS Connectivity

DNS alone does not prove port 443 is reachable. After resolution succeeds, confirm TCP and TLS with tools the CLI also relies on.

A quick HTTPS probe against the Regional endpoint:

bash
curl -sS -o /dev/null -w "http_code=%{http_code} connect=%{time_connect}\n" --connect-timeout 5 https://s3.ap-south-1.amazonaws.com/
output
http_code=307 connect=0.026355

HTTP 307 is enough to show DNS, TCP, and TLS succeeded because the endpoint returned an HTTP response. The exact status code is less important than distinguishing a real response from timeout, DNS failure, or connection refusal.

Test raw TCP to port 443:

bash
nc -zv s3.ap-south-1.amazonaws.com 443
output
Ncat: Version 7.92 ( https://nmap.org/ncat )
Ncat: Connected to 3.5.208.54:443.

When nc reports Connection refused or times out while dig returns addresses, suspect host firewall rules, outbound security group rules, or missing NAT from a private subnet.


Check Proxy Variables

Many Linux workstations and CI images export HTTP_PROXY or HTTPS_PROXY. The AWS CLI honors these variables and routes API traffic through the proxy.

Reproduce a proxy failure:

bash
HTTPS_PROXY=http://127.0.0.1:9 aws s3 ls
output
aws: [ERROR]: Failed to connect to proxy URL: "http://127.0.0.1:9"

List proxy-related variables in the same shell that runs aws:

bash
env | grep -i proxy

If the output is empty, the shell is not exporting proxy variables—check systemd unit files, CI YAML, and /etc/environment on the host.

Variable Role
HTTPS_PROXY Proxy URL for HTTPS API calls (most AWS endpoints)
HTTP_PROXY Fallback for plain HTTP endpoints
NO_PROXY Exception list: matching destinations are contacted directly instead of through the configured proxy (include 169.254.169.254 for IMDS on EC2)

To test without proxy interference for one command:

bash
env -u HTTPS_PROXY -u HTTP_PROXY -u https_proxy -u http_proxy aws sts get-caller-identity

Avoid defining both uppercase and lowercase proxy variables with different values. AWS documents that when both forms exist, lowercase variables can take precedence—use one consistent form in shell profiles and CI images.

If that succeeds while the normal shell fails, update the proxy URL. For EC2 instances behind a proxy, AWS documents excluding IMDS with NO_PROXY=169.254.169.254. Add required AWS service hostnames or domain suffixes to NO_PROXY according to your proxy implementation and corporate policy.


If the AWS CLI runs on a laptop, the request normally reaches AWS through the normal internet connection. If it runs on an EC2 instance in a private subnet, that instance still needs a path to the AWS service—usually through NAT or an appropriate VPC endpoint.

On a private EC2 instance without NAT or an appropriate VPC endpoint, outbound connections to public AWS endpoints time out or fail even when credentials and Region are correct. The error still quotes a public hostname such as s3.ap-south-1.amazonaws.com.

Public endpoint without egress:

┌──────────────┐     no NAT / no route   ┌─────────────────────────┐
│ EC2 private  │ ───────────────────────► │ s3.ap-south-1.amazonaws │
│ subnet       │   connection fails       │ .com (public endpoint)  │
└──────────────┘                          └─────────────────────────┘

S3 supports two VPC endpoint models. A gateway endpoint is associated with route tables and does not create endpoint ENIs. An interface endpoint is powered by AWS PrivateLink, creates private IPs in selected subnets, and uses security groups.

Option 1 — S3 gateway endpoint:

   EC2 private subnet
            |
            | route table
            v
   S3 gateway endpoint
            |
            v
        Amazon S3

Option 2 — S3 interface endpoint:

          EC2
           |
           | private IP / DNS
           v
 Interface endpoint ENI
           |
           | AWS PrivateLink
           v
        Amazon S3

Gateway endpoints add routes to selected VPC route tables. Interface endpoints are created in subnets and controlled by security groups; enabling Private DNS lets standard Regional S3 hostnames resolve through the interface endpoint where appropriate.

Checks from the instance:

  • curl -Iv --connect-timeout 5 https://s3.ap-south-1.amazonaws.com/ — does TCP complete?
  • ip route get $(dig +short s3.ap-south-1.amazonaws.com | head -1) — which interface and next hop does the kernel use?
  • Route tables: private subnets need 0.0.0.0/0 → NAT gateway for public endpoints, or a prefix list / gateway endpoint route for S3/DynamoDB gateway endpoints
  • For interface endpoints, verify Private DNS names, endpoint security groups, subnet selection, and enableDnsSupport / enableDnsHostnames on the VPC

Misconfigured VPC endpoints can also change how the service hostname resolves. For an interface endpoint with Private DNS enabled, seeing a private IP is normally expected—the important question is whether that private IP belongs to the endpoint and is reachable from the instance. If DNS resolves unexpectedly, verify the endpoint's Private DNS setting, VPC DNS attributes, Route 53 Resolver configuration, and the endpoint subnets and security group.


Use --debug Safely

--debug shows which endpoint the CLI selected and where the connection attempt stopped. AWS CLI uses the botocore library internally to select service endpoints and send requests. Use --debug after the quick DNS and curl checks, not as the first step.

bash
aws s3 ls --endpoint-url https://127.0.0.1:9 --debug 2>&1 | grep -E 'Endpoint|endpoint|connect|proxy|Connection|urllib' | head -18
output
2026-09-27 21:17:33,672 - MainThread - botocore.regions - DEBUG - Calling endpoint provider with parameters: {'Region': 'ap-south-1', 'UseFIPS': False, 'UseDualStack': False, 'Endpoint': 'https://127.0.0.1:9', 'ForcePathStyle': True, 'Accelerate': False, 'UseGlobalEndpoint': False, 'DisableMultiRegionAccessPoints': False, 'UseArnRegion': True, 'DisableS3ExpressSessionAuth': False}
2026-09-27 21:17:33,673 - MainThread - botocore.regions - DEBUG - Endpoint provider result: https://127.0.0.1:9
2026-09-27 21:17:33,678 - MainThread - urllib3.connectionpool - DEBUG - Starting new HTTPS connection (1): 127.0.0.1:9
2026-09-27 21:17:33,679 - MainThread - botocore.endpoint - DEBUG - Exception received when sending HTTP request.
  File "urllib3/connection.py", line 204, in _new_conn
  File "urllib3/util/connection.py", line 85, in create_connection

The Endpoint provider result line shows the final endpoint selected by the CLI. Extract its hostname and port when testing with dig, curl, or nc. For example, when the result is https://127.0.0.1:9, the hostname is 127.0.0.1 and the port is 9.

Redact or delete Authorization and X-Amz-Security-Token lines before sharing logs—--debug prints signing material.


Verify

After clearing a bad --endpoint-url, fixing proxy variables, or restoring VPC egress, confirm the CLI reaches AWS with a small read-only call.

Clear proxy and endpoint overrides from the shell:

bash
unset HTTPS_PROXY HTTP_PROXY https_proxy http_proxy AWS_ENDPOINT_URL

Also check for service-specific endpoint variables before concluding the override is gone:

bash
env | grep '^AWS_ENDPOINT_URL'

sts is a lightweight Regional call — use it to confirm the endpoint is reachable:

bash
aws sts get-caller-identity --query Account --output text
output
123456789012

A numeric account ID means the STS Regional endpoint was reachable and credentials signed the request successfully. STS is a useful general connectivity check, but if S3 was the failing service, also rerun the original S3 command because service-specific endpoint overrides and VPC endpoints can behave differently per service.

List S3 buckets as a second check when S3 was the failing service:

bash
aws s3 ls

An empty list still counts as success—the connection worked even when the account has no buckets.


Troubleshooting

Symptom Likely cause Fix
Could not connect and the URL shows 127.0.0.1 or an unexpected private/custom endpoint Stale or unintended --endpoint-url, AWS_ENDPOINT_URL*, or profile endpoint configuration Verify whether the override is intentional (LocalStack, internal proxy, VPC endpoint DNS); remove it if not
Failed to connect to proxy URL Wrong or unreachable corporate proxy Fix proxy URL, credentials, or NO_PROXY list
dig returns no answers for *.amazonaws.com Custom DNS resolver, split-horizon, or offline host Fix resolver forwarders; test with dig @8.8.8.8 only as a comparison
dig works; nc to 443 times out Security group, NACL, firewall, or missing NAT Open outbound 443; add NAT or VPC endpoint routes
Works on laptop, fails on private EC2 No internet egress path or missing VPC endpoint Add NAT gateway, gateway endpoint routes, or interface endpoint with Private DNS
AccessDenied after connection fixes IAM policy, SCP, or resource policy Switch to IAM troubleshooting guides

Summary

Could not connect to the endpoint URL means the CLI could not establish a connection to the service endpoint. Start with the hostname shown in the error and test it with dig, curl, and nc before touching IAM policies or rotating access keys.

Use aws configure list to see the effective Region and whether environment variables override profile settings. DNS must resolve the expected hostname, and TCP/TLS to port 443 must succeed from the same host that runs aws. Check global and service-specific AWS_ENDPOINT_URL_* variables and profile endpoint configuration—not only Region defaults.

Proxy environment variables can block traffic before it leaves the machine; avoid mixing uppercase and lowercase proxy exports. Private EC2 subnets need public egress through NAT, gateway endpoint routes, or interface endpoints with appropriate DNS—not an internet gateway alone on a private instance.

--debug confirms which endpoint botocore chose and where urllib3 stopped, but trim signing headers from shared logs. When aws sts get-caller-identity returns an account ID again, the STS path is healthy—rerun the original failing service command to confirm service-specific routing and overrides.


References


Frequently Asked Questions

Is this an IAM permission error?

No. Could not connect to the endpoint URL means the CLI could not establish a usable connection to the hostname in the message. IAM errors such as AccessDenied appear only after the request reaches AWS and fails authorization. Fix DNS, proxy, firewall, and VPC egress first.

Does AWS CLI need internet access?

For default public AWS endpoints, the host needs a network path to the service. That may be direct internet access, NAT from a private subnet, an interface VPC endpoint, or—where the service supports it—a gateway endpoint such as the S3 gateway endpoint. LocalStack and custom --endpoint-url values use different hostnames.

Can a VPC endpoint fix this error?

Yes, when the instance sits in a private subnet without NAT. For S3, a gateway endpoint adds routes to selected VPC route tables. An interface endpoint creates private ENIs in selected subnets and uses security groups; enabling Private DNS lets standard Regional S3 hostnames resolve through the interface endpoint where appropriate. Without those routes or DNS settings, calls to s3.region.amazonaws.com still fail with connection errors.

Finished reading?Beta Get the key takeaways in seconds, then ask follow-up questions
Deepak Prasad

R&D Engineer

Founder of GoLinuxCloud with 15+ years of expertise in Linux, Python, Go, Laravel, DevOps, Kubernetes, Git, Shell scripting, OpenShift, AWS, Networking, and Security. With extensive experience, he excels across development, DevOps, networking, and security, delivering robust and efficient solutions for diverse projects.

  • Go (programming language)
  • Python (programming language)
  • DevOps
  • Computer Security
  • Cloud Computing
  • Kubernetes
  • Linux
  • Ansible (software)