| 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 |
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 hereEndpoint 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:
aws s3 ls --endpoint-url https://127.0.0.1:9aws: [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:
HTTPS_PROXY=http://127.0.0.1:9 aws s3 lsaws: [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:
aws configure list Name Value Type Location
---- ----- ---- --------
profile <not set> None None
access_key ****************ABCD env
secret_key ****************WXYZ env
region ap-south-1 env AWS_REGIONThe 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:
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.
export AWS_ENDPOINT_URL_S3=http://127.0.0.1:4566With only the S3 override set, list buckets to see which hostname the CLI uses:
aws s3 lsThe 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 listmatches the resources being accessed - No accidental
--endpoint-urlleft from LocalStack, MinIO, or an old PrivateLink test - No stale
AWS_ENDPOINT_URLorAWS_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=trueto ignore configured custom endpoint URLs. An explicit--endpoint-urlstill 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:
dig +short s3.ap-south-1.amazonaws.com3.5.208.54
3.5.213.238
3.5.213.153Multiple A records are normal for AWS service endpoints such as S3.
A deliberately invalid Regional hostname returns no answers:
dig +short s3.not-a-real-region.amazonaws.comWith no DNS answers, the CLI fails when that hostname is forced through --endpoint-url:
aws s3 ls --endpoint-url https://s3.not-a-real-region.amazonaws.comaws: [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:
curl -sS -o /dev/null -w "http_code=%{http_code} connect=%{time_connect}\n" --connect-timeout 5 https://s3.ap-south-1.amazonaws.com/http_code=307 connect=0.026355HTTP 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:
nc -zv s3.ap-south-1.amazonaws.com 443Ncat: 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:
HTTPS_PROXY=http://127.0.0.1:9 aws s3 lsaws: [ERROR]: Failed to connect to proxy URL: "http://127.0.0.1:9"List proxy-related variables in the same shell that runs aws:
env | grep -i proxyIf 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:
env -u HTTPS_PROXY -u HTTP_PROXY -u https_proxy -u http_proxy aws sts get-caller-identityAvoid 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.
Check VPC Egress or PrivateLink
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 S3Option 2 — S3 interface endpoint:
EC2
|
| private IP / DNS
v
Interface endpoint ENI
|
| AWS PrivateLink
v
Amazon S3Gateway 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/enableDnsHostnameson 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.
aws s3 ls --endpoint-url https://127.0.0.1:9 --debug 2>&1 | grep -E 'Endpoint|endpoint|connect|proxy|Connection|urllib' | head -182026-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_connectionThe 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:
unset HTTPS_PROXY HTTP_PROXY https_proxy http_proxy AWS_ENDPOINT_URLAlso check for service-specific endpoint variables before concluding the override is gone:
env | grep '^AWS_ENDPOINT_URL'sts is a lightweight Regional call — use it to confirm the endpoint is reachable:
aws sts get-caller-identity --query Account --output text123456789012A 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:
aws s3 lsAn 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
- AWS service endpoints — Regional hostname patterns and endpoint entry points
- AWS CLI named profiles — Region and output settings in
config - AWS CLI environment variables —
AWS_REGION, proxy variables,AWS_ENDPOINT_URL, and service-specificAWS_ENDPOINT_URL_<SERVICE>overrides - AWS CLI service-specific endpoints — endpoint precedence and profile endpoint configuration
- Amazon S3 endpoints and quotas — Regional hostname patterns
- VPC endpoints (AWS PrivateLink) — interface and gateway endpoints
- AWS CLI return codes — exit code
255for connection failures
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.

