The AWS Command Line Interface (AWS CLI) is a unified tool to manage your AWS services from the terminal. With a single tool, you can control multiple AWS services and automate them through scripts. This guide covers AWS CLI version 1 (v1.44.85).
1. Quick Start
Get up and running in under five minutes:
# Install
pip install awscli
# Configure credentials
aws configure
You will be prompted for four values:
AWS Access Key ID [None]: AKIAIOSFODNN7EXAMPLE
AWS Secret Access Key [None]: wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY
Default region name [None]: us-east-1
Default output format [None]: json
Test the installation:
aws --version
Expected output:
aws-cli/1.44.85 Python/3.11.6 Linux/6.1.0 botocore/1.42.95
Tip
Run
aws sts get-caller-identityto verify your credentials are working. If it returns your account ID, ARN, and user ID, you are properly authenticated.
2. Installation
Requirements
- Python 3.9 or later
- pip (Python package manager)
Install via pip
pip install awscli
To install a specific version:
pip install awscli==1.44.85
Upgrade
pip install --upgrade awscli
Verify installation
aws --version
Dependencies
AWS CLI v1 installs the following dependencies automatically:
| Package | Version |
|---|---|
| botocore | 1.42.95 |
| docutils | latest compatible |
| s3transfer | latest compatible |
| PyYAML | latest compatible |
| colorama | latest compatible |
| rsa | latest compatible |
Important
AWS CLI v1 and v2 are separate products. This guide documents v1 only. Do not mix installation methods or expect v2-specific features (such as the built-in installer or auto-prompt) to work with v1.
Shell Completion
Enable tab completion for commands and parameters:
Bash:
complete -C aws_completer aws
Add this line to your ~/.bashrc to make it persistent.
Zsh:
source aws_zsh_completer.sh
Add this line to your ~/.zshrc.
3. Configuration
Configuration Files
AWS CLI uses two files:
| File | Purpose |
|---|---|
~/.aws/credentials |
Access keys (shared across SDKs) |
~/.aws/config |
Region, output format, profiles, other settings |
Initial Setup
aws configure
This creates both files with your default profile. To configure a named profile:
aws configure --profile production
Config File Format
~/.aws/credentials:
[default]
aws_access_key_id = AKIAIOSFODNN7EXAMPLE
aws_secret_access_key = wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY
[production]
aws_access_key_id = AKIAI44QH8DHBEXAMPLE
aws_secret_access_key = je7MtGbClwBF/2Zp9Utk/h3yCo8nvbEXAMPLEKEY
~/.aws/config:
[default]
region = us-east-1
output = json
[profile production]
region = eu-west-1
output = table
Note
In the credentials file, section names are just
[profilename]. In the config file, non-default profiles must use the prefix[profile profilename].
Environment Variables
Environment variables override config file values:
| Variable | Purpose |
|---|---|
AWS_ACCESS_KEY_ID |
Access key |
AWS_SECRET_ACCESS_KEY |
Secret key |
AWS_DEFAULT_REGION |
Default region |
AWS_DEFAULT_OUTPUT |
Output format (json/text/table) |
AWS_CONFIG_FILE |
Path to config file |
AWS_SHARED_CREDENTIALS_FILE |
Path to credentials file |
AWS_CA_BUNDLE |
Path to CA certificate bundle |
AWS_DATA_PATH |
Additional data search paths |
Profiles
Use the --profile flag to switch between configured profiles:
aws s3 ls --profile production
SSO Login
If your organization uses AWS SSO:
aws sso login --profile my-sso-profile
Command Aliases
Create shortcuts in ~/.aws/cli/alias (INI format):
[toplevel]
whoami = sts get-caller-identity
running = ec2 describe-instances --filters Name=instance-state-name,Values=running
myip = !curl -s https://checkip.amazonaws.com
Aliases in the [toplevel] section are invoked as:
aws whoami
aws running
External aliases (prefixed with !) run shell commands:
aws myip
4. Core Usage
Command Structure
aws [global-options] <service> <operation> [parameters]
Examples:
aws ec2 describe-instances
aws s3 ls
aws lambda list-functions --region us-west-2
Global Options
| Option | Description |
|---|---|
--version |
Display version and exit |
--output |
Output format: json, text, or table |
--region |
AWS region to target |
--profile |
Named profile to use |
--endpoint-url |
Override service endpoint URL |
--no-verify-ssl |
Disable SSL certificate verification |
--no-paginate |
Disable automatic pagination |
--query |
JMESPath query to filter output |
--debug |
Enable debug logging |
--cli-read-timeout |
Read timeout in seconds |
--cli-connect-timeout |
Connection timeout in seconds |
--no-sign-request |
Do not sign requests (for public resources) |
--ca-bundle |
Path to CA certificate bundle |
--color |
Color output: on, off, or auto |
Output Formats
JSON (default) -- structured, machine-readable:
aws iam list-users --output json
{
"Users": [
{
"UserName": "alice",
"UserId": "AIDAEXAMPLE1",
"Arn": "arn:aws:iam::123456789012:user/alice"
}
]
}
Table -- human-readable, formatted columns:
aws iam list-users --output table
------------------------------------------------------------
| ListUsers |
+----------+----------------+-----------------------------+
| UserName | UserId | Arn |
+----------+----------------+-----------------------------+
| alice | AIDAEXAMPLE1 | arn:aws:iam::123...:user/al |
+----------+----------------+-----------------------------+
Text -- tab-delimited, suitable for grep/awk/cut:
aws iam list-users --output text
USERS alice AIDAEXAMPLE1 arn:aws:iam::123456789012:user/alice
Filtering Output with --query
The --query option accepts JMESPath expressions:
# Get just instance IDs
aws ec2 describe-instances --query 'Reservations[].Instances[].InstanceId'
# Filter by state
aws ec2 describe-instances \
--query 'Reservations[].Instances[?State.Name==`running`].InstanceId'
# Format as table with selected fields
aws ec2 describe-instances \
--query 'Reservations[].Instances[].[InstanceId, State.Name, InstanceType]' \
--output table
Input Methods
Inline JSON:
aws ec2 create-tags --resources i-1234567890abcdef0 \
--tags '[{"Key":"Name","Value":"MyInstance"}]'
Shorthand syntax:
aws ec2 create-tags --resources i-1234567890abcdef0 \
--tags Key=Name,Value=MyInstance
From a file (file:// prefix):
aws ec2 run-instances --cli-input-json file://params.json
Binary file content (fileb:// prefix):
aws lambda update-function-code \
--function-name my-function \
--zip-file fileb://function.zip
Note
Use
file://for text content (UTF-8) andfileb://for binary content (zip files, images, etc.).
Getting Help
# General help
aws help
# Service help (lists all operations)
aws ec2 help
# Operation help (shows parameters, examples)
aws ec2 describe-instances help
Waiters
Wait for a resource to reach a specific state before proceeding:
aws ec2 wait instance-running --instance-ids i-1234567890abcdef0
The command blocks until the instance is running (or times out). Useful in scripts to ensure sequential operations succeed.
Pagination
By default, AWS CLI automatically paginates results. To get all results in one call:
aws s3api list-objects --bucket my-bucket --no-paginate
5. Common Tasks
5.1 S3: Upload a File
aws s3 cp myfile.txt s3://my-bucket/myfile.txt
Expected output:
upload: ./myfile.txt to s3://my-bucket/myfile.txt
Upload an entire directory:
aws s3 cp ./local-dir s3://my-bucket/prefix/ --recursive
5.2 S3: Download Files
aws s3 cp s3://my-bucket/myfile.txt ./myfile.txt
Download a directory:
aws s3 cp s3://my-bucket/prefix/ ./local-dir/ --recursive
5.3 S3: Sync a Directory
Sync uploads only changed files (like rsync):
aws s3 sync ./local-dir s3://my-bucket/backup/
Sync from S3 to local:
aws s3 sync s3://my-bucket/backup/ ./local-dir/
Delete files in destination that do not exist in source:
aws s3 sync ./local-dir s3://my-bucket/backup/ --delete
5.4 S3: List and Remove
List buckets:
aws s3 ls
List objects in a bucket:
aws s3 ls s3://my-bucket/
aws s3 ls s3://my-bucket/prefix/ --recursive
Remove a file:
aws s3 rm s3://my-bucket/myfile.txt
Remove all objects with a prefix:
aws s3 rm s3://my-bucket/prefix/ --recursive
5.5 S3: Create and Delete Buckets
aws s3 mb s3://my-new-bucket
aws s3 rb s3://my-empty-bucket
aws s3 rb s3://my-bucket --force # removes all objects first
5.6 EC2: Launch an Instance
aws ec2 run-instances \
--image-id ami-0abcdef1234567890 \
--instance-type t3.micro \
--key-name my-keypair \
--security-group-ids sg-0123456789abcdef0 \
--count 1
5.7 EC2: List Running Instances
aws ec2 describe-instances \
--filters Name=instance-state-name,Values=running \
--query 'Reservations[].Instances[].[InstanceId, InstanceType, PublicIpAddress]' \
--output table
5.8 EC2: Stop and Terminate
aws ec2 stop-instances --instance-ids i-1234567890abcdef0
aws ec2 terminate-instances --instance-ids i-1234567890abcdef0
5.9 Lambda: Deploy a Function
aws lambda create-function \
--function-name my-function \
--runtime python3.12 \
--role arn:aws:iam::123456789012:role/lambda-role \
--handler lambda_function.handler \
--zip-file fileb://function.zip
Update function code:
aws lambda update-function-code \
--function-name my-function \
--zip-file fileb://function.zip
5.10 Lambda: Invoke a Function
aws lambda invoke \
--function-name my-function \
--payload '{"key": "value"}' \
output.json
5.11 IAM: Manage Users
# Create user
aws iam create-user --user-name developer
# Create access key
aws iam create-access-key --user-name developer
# Attach policy
aws iam attach-user-policy \
--user-name developer \
--policy-arn arn:aws:iam::aws:policy/AmazonS3ReadOnlyAccess
# List users
aws iam list-users --output table
5.12 CloudFormation: Deploy a Stack
aws cloudformation create-stack \
--stack-name my-stack \
--template-body file://template.yaml \
--capabilities CAPABILITY_IAM
# Wait for completion
aws cloudformation wait stack-create-complete --stack-name my-stack
5.13 Logs: Tail CloudWatch Logs
aws logs get-log-events \
--log-group-name /aws/lambda/my-function \
--log-stream-name '2026/05/06/[$LATEST]abc123' \
--limit 50
5.14 STS: Check Current Identity
aws sts get-caller-identity
Expected output:
{
"UserId": "AIDAEXAMPLE",
"Account": "123456789012",
"Arn": "arn:aws:iam::123456789012:user/myuser"
}
5.15 CloudFront: Create an Invalidation
aws cloudfront create-invalidation \
--distribution-id E1A2B3C4D5E6F7 \
--paths "/index.html" "/css/*"
6. Troubleshooting
6.1 "groff or mandoc" Not Found
Error:
Could not find executable named "groff" or "mandoc"
Cause: The help system renders man pages using groff or mandoc, which are not installed.
Solution:
# Ubuntu/Debian
sudo apt install groff
# macOS (usually pre-installed, but if missing)
brew install groff
# Amazon Linux / RHEL
sudo yum install groff
Prevention: Install groff as part of your base system provisioning.
6.2 "Unable to load paramfile" Errors
Error:
Unable to load paramfile file://config.json: [Errno 2] No such file or directory
Cause: The file:// path is relative to your current working directory, or the file does not exist.
Solution: Use an absolute path or verify your working directory:
aws lambda update-function-code \
--function-name my-func \
--zip-file fileb:///home/user/deploy/function.zip
Prevention: Always use absolute paths in scripts.
6.3 "Invalid choice, valid choices are..."
Error:
Invalid choice: 'ec2-describe-instances', valid choices are: ...
Cause: Typo in the command, or using old-style command format.
Solution: AWS CLI v1 uses aws <service> <operation> format (space-separated, not hyphens):
# Wrong
aws ec2-describe-instances
# Correct
aws ec2 describe-instances
6.4 "Unknown options" Error
Error:
Unknown options: --my-flag
Cause: The parameter does not exist for this operation, or there is a typo.
Solution: Check available parameters:
aws ec2 describe-instances help
6.5 "Bad value for --endpoint-url"
Error:
Bad value for --endpoint-url "myendpoint.example.com": scheme is missing...
Cause: The endpoint URL must include https:// or http://.
Solution:
# Wrong
aws s3 ls --endpoint-url myendpoint.example.com
# Correct
aws s3 ls --endpoint-url https://myendpoint.example.com
6.6 "Bad value for --query"
Error:
Bad value for --query "Reservations[.Instances[]": invalid expression...
Cause: Invalid JMESPath syntax.
Solution: Validate your JMESPath expression. Common issues:
- Missing closing brackets
- Using single quotes inside the expression on Windows (use double quotes and escape)
- Incorrect field names (case-sensitive)
# Test incrementally
aws ec2 describe-instances --query 'Reservations'
aws ec2 describe-instances --query 'Reservations[0]'
aws ec2 describe-instances --query 'Reservations[].Instances[].InstanceId'
6.7 Credentials Not Found
Error:
Unable to locate credentials. You can configure credentials by running "aws configure".
Cause: No credentials in environment variables, config files, or instance metadata.
Solution:
- Run
aws configureto set up credentials - Or set environment variables:
export AWS_ACCESS_KEY_ID=AKIAEXAMPLE
export AWS_SECRET_ACCESS_KEY=wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY
- Or verify your credentials file exists at
~/.aws/credentials
6.8 Region Not Specified
Error:
You must specify a region. You can also configure your region by running "aws configure".
Cause: No region set in config, environment, or command line.
Solution:
# Per command
aws ec2 describe-instances --region us-east-1
# Or set globally
aws configure set region us-east-1
# Or environment variable
export AWS_DEFAULT_REGION=us-east-1
6.9 SSL Certificate Verification Failed
Error:
SSL validation failed for https://...
Cause: Corporate proxy, custom CA, or outdated certificates.
Solution:
# Point to your CA bundle
aws s3 ls --ca-bundle /path/to/custom-ca-bundle.crt
# Or set globally
export AWS_CA_BUNDLE=/path/to/custom-ca-bundle.crt
# As a last resort (NOT recommended for production)
aws s3 ls --no-verify-ssl
Caution
Using
--no-verify-ssldisables all certificate verification. Only use this for debugging, never in production or scripts handling sensitive data.
Prevention: Keep your system CA certificates updated. If behind a corporate proxy, add the proxy CA to your bundle.
6.10 SSO Login Fails to Open Browser (WSL)
Error: Running aws sso login in WSL fails with errors related to gio or the browser not opening.
Cause: WSL does not have a native graphical browser. The SSO flow tries to open one via xdg-open or gio.
Solution:
- Set your Windows browser as the default:
export BROWSER="/mnt/c/Program Files/Google/Chrome/Application/chrome.exe"
- Or manually copy the URL printed to the terminal and paste it into your Windows browser.
Prevention: Add the BROWSER export to your ~/.bashrc in WSL.
6.11 Access Denied
Error:
An error occurred (AccessDenied) when calling the <Operation> operation: User: arn:aws:iam::...
Cause: The IAM identity does not have permission for the requested action.
Solution:
- Verify which identity you are using:
aws sts get-caller-identity - Check that the required IAM policy is attached
- Verify you are in the correct account and region
6.12 Timeout Errors
Error:
Connect timeout on endpoint URL...
Cause: Network issues, DNS resolution failure, or firewall blocking.
Solution:
# Increase timeouts
aws s3 ls --cli-connect-timeout 30 --cli-read-timeout 60
Check that you can reach AWS endpoints:
curl -v https://sts.amazonaws.com
Warning
If you are behind a corporate firewall or VPN, ensure that outbound HTTPS (port 443) is allowed to AWS service endpoints (
*.amazonaws.com).
7. FAQ
Q: How do I switch between multiple AWS accounts?
Use named profiles. Configure each account with aws configure --profile <name>, then use --profile <name> on each command, or set export AWS_PROFILE=<name> for the session.
Q: What is the difference between aws s3 and aws s3api?
aws s3 provides high-level commands (cp, sync, mv, ls, rm, mb, rb) with familiar filesystem-like syntax. aws s3api exposes the full S3 API with all parameters. Use aws s3 for everyday tasks and aws s3api when you need fine-grained control.
Q: Can I use AWS CLI without credentials (for public resources)?
Yes. Use --no-sign-request to skip authentication:
aws s3 ls s3://public-bucket --no-sign-request
Q: How do I get output as plain text for scripting?
Use --output text combined with --query:
INSTANCE_ID=$(aws ec2 describe-instances \
--query 'Reservations[0].Instances[0].InstanceId' \
--output text)
Q: How do I use AWS CLI with a proxy?
Set the standard proxy environment variables:
export HTTP_PROXY=http://proxy.example.com:8080
export HTTPS_PROXY=http://proxy.example.com:8080
Q: Where are the debug logs?
Use --debug to print detailed logs to stderr:
aws s3 ls --debug 2>debug.log
This includes HTTP request/response details, credential resolution, and retry logic.
Q: How do I paginate through large result sets manually?
Use --max-items and --starting-token:
aws s3api list-objects --bucket my-bucket --max-items 100
# Use the NextToken from output:
aws s3api list-objects --bucket my-bucket --max-items 100 --starting-token eyJ...
Q: Can I pipe JSON input from another command?
Yes, but note that --cli-input-json requires file://. You can use process substitution on Linux/macOS:
aws ec2 run-instances --cli-input-json file://<(generate_params.sh)
Or write to a temporary file first.
Q: What Python versions are supported?
AWS CLI v1.44.85 requires Python 3.9 or later.
Q: How do I create command aliases?
Create or edit ~/.aws/cli/alias:
[toplevel]
whoami = sts get-caller-identity
ls-instances = ec2 describe-instances --query 'Reservations[].Instances[].[InstanceId,State.Name]' --output table
Then use them as aws whoami or aws ls-instances.
Tip
For architecture details, configuration internals, extension mechanisms, and security hardening, see the Admin Guide.