| Package | aws-cli/2.37.3 |
|---|---|
| AWS Region | ap-south-1 for the examples. Shared config and credential files are machine-specific; IAM is global within an AWS account |
| Lab environment | Workstation with AWS CLI v2 and configured credentials — AWS CLI tutorial Install AWS CLI on Ubuntu · Install AWS CLI on Debian |
| Privilege | Permission to create IAM users, access keys, and roles when following the setup examples; read access to local ~/.aws/ files for day-to-day switching |
| Scope | Configure multiple AWS CLI named profiles, switch between AWS accounts with --profile or AWS_PROFILE, verify the active account or role using aws sts get-caller-identity, and troubleshoot profile and credential precedence. Includes IAM user, assumed-role, and brief SSO examples. Does not cover missing credentials or invalid keys — see Unable to locate credentials and InvalidClientTokenId. |
| Related guides | AWS CLI Tutorial Which credentials AWS CLI uses Unable to locate credentials Fix Terraform AWS credentials error AWS Tutorial |
If you work with multiple AWS accounts, you do not need to run aws configure again every time you switch accounts. AWS CLI named profiles keep separate configuration for environments such as dev and prod, then let you choose the one you want with --profile or AWS_PROFILE.
The important part is verifying which identity the CLI actually selected before a command touches production. Every profile switch in this guide is checked with aws sts get-caller-identity, which shows the active AWS account and IAM user or role.
Quick Answer: Switch Between AWS CLI Profiles
Create a separate named profile for each AWS account, role, or authentication setup you need to select. In this example, dev and prod point at two different AWS accounts.
Create the profiles:
aws configure --profile devAdd a second profile for the production account:
aws configure --profile prodUse one profile for one command:
aws sts get-caller-identity --profile prodOr make it the profile for this shell:
export AWS_PROFILE=prodConfirm the active account before running anything destructive:
aws sts get-caller-identity| Goal | Command or setting |
|---|---|
| List profile names | aws configure list-profiles |
| One command with a named profile | aws sts get-caller-identity --profile prod |
| Default profile for the shell session | export AWS_PROFILE=prod |
| When both are set | --profile on the command wins over AWS_PROFILE |
When using AWS_PROFILE |
Explicit credential environment variables can override credentials stored in that profile |
When using --profile name |
The explicitly selected profile is used for that command |
| Confirm active identity | aws sts get-caller-identity (same flags and env as the next command) |
The sections below show where profiles are stored, how SSO and role profiles work, and how to avoid credential conflicts when switching accounts.
Create Multiple AWS CLI Profiles
Create dev and prod profiles
For access-key-based profiles, AWS CLI commonly stores credentials and configuration in two shared files:
| File | Typical contents |
|---|---|
~/.aws/credentials (or AWS_SHARED_CREDENTIALS_FILE) |
aws_access_key_id, aws_secret_access_key, optional aws_session_token |
~/.aws/config (or AWS_CONFIG_FILE) |
region, output, SSO settings, role_arn, source_profile |
This layout applies to the access-key example below. SSO and role-based profiles work differently and may not store long-lived credentials in ~/.aws/credentials.
Profile sections use different syntax in each file:
- Credentials file:
[profile-name]without aprofileprefix - Config file:
[profile profile-name]with theprofileprefix (except[default])
aws login instead of long-lived IAM user access keys. Named profiles work with those authentication methods as well.
Create a profile interactively for the dev account:
aws configure --profile devThe prompts look like this:
AWS Access Key ID [None]: ...
AWS Secret Access Key [None]: ...
Default region name [None]: ap-south-1
Default output format [None]: jsonaws configure is asking for credentials and defaults for this named profile. The access key ID identifies the AWS credential being used, while the secret access key is used to cryptographically sign API requests. Together, they authenticate the IAM user associated with those credentials. The Region becomes the default for regional AWS services unless you override it on a command. json controls how AWS CLI displays command output; it does not affect authentication or which account is selected.
Repeat for production:
aws configure --profile prodThe access key and secret go into the credentials file; Region and output format go into the config file under [profile dev] and [profile prod].
Where AWS stores named profiles
List every profile name the CLI can see:
aws configure list-profilesdev
prod
auditA multi-account layout looks like this (secrets replaced with placeholders):
--- ~/.aws/credentials ---
[dev]
aws_access_key_id = AKIADEVKEYEXAMPLE
aws_secret_access_key = ***
[prod]
aws_access_key_id = AKIAPRODKEYEXAMPLE
aws_secret_access_key = ***
--- ~/.aws/config ---
[profile dev]
region = ap-south-1
output = json
[profile prod]
region = ap-south-1
output = json
[profile audit]
region = ap-south-1
output = json
role_arn = arn:aws:iam::222222222222:role/audit-readonly
source_profile = prodNever commit AWS credential files to source control. If ~/.aws/credentials contains long-lived access keys, ensure the file is readable only by your user, for example with chmod 600 ~/.aws/credentials. Prefer short-term credentials instead of storing long-lived access keys when possible.
Optional: use an SSO profile
A named profile does not have to contain long-lived access keys. It can also point to an IAM Identity Center configuration:
aws configure sso --profile prod-ssoSign in through the browser flow:
aws sso login --profile prod-ssoConfirm the SSO session with the same profile name:
aws sts get-caller-identity --profile prod-ssoHere, prod-sso is just another named profile. The difference is how it obtains credentials: through IAM Identity Center rather than access keys stored in ~/.aws/credentials. Once authenticated, switch and verify SSO profiles with the same --profile or AWS_PROFILE techniques used elsewhere in this guide.
Use a Profile for One AWS CLI Command
Pass --profile when a single command should use a named profile without changing the shell default:
aws sts get-caller-identity --profile prod{
"UserId": "AIDAXXXXXXXXXXXXXXXXX",
"Account": "222222222222",
"Arn": "arn:aws:iam::222222222222:user/prod-admin"
}Inspect what that one invocation loads:
aws configure list --profile prodNAME : VALUE : TYPE : LOCATION
profile : prod : manual : --profile
access_key : ****************5TGM : shared-credentials-file :
secret_key : ****************Iwdx : shared-credentials-file :
region : ap-south-1 : config-file : ~/.aws/configThe LOCATION column confirms keys came from the shared credentials file, not from exported environment variables. --profile is usually safer for scripts and one-off administrative commands because the intended profile is visible directly in the command instead of depending on the shell's current environment.
Switch the AWS Profile for Your Shell
Export AWS_PROFILE when every command in the session should share one profile:
export AWS_PROFILE=prodConfirm the shell picked it up:
aws sts get-caller-identity{
"UserId": "AIDAXXXXXXXXXXXXXXXXX",
"Account": "222222222222",
"Arn": "arn:aws:iam::222222222222:user/prod-admin"
}The configure list output shows where each value was resolved:
aws configure listNAME : VALUE : TYPE : LOCATION
profile : prod : env : ['AWS_PROFILE', 'AWS_DEFAULT_PROFILE']
access_key : ****************5TGM : shared-credentials-file :
secret_key : ****************Iwdx : shared-credentials-file :
region : ap-south-1 : config-file : ~/.aws/configHere, AWS_PROFILE selects prod, while the access key still comes from ~/.aws/credentials. The TYPE and LOCATION columns make it easy to see where each value came from.
To return to the implicit default profile:
unset AWS_PROFILE AWS_DEFAULT_PROFILEAdd AWS_PROFILE to .bashrc, .zshrc, or another shell startup file only if you really want that profile selected every time you open a shell. On machines used with several AWS accounts, setting it manually is safer because the active account is less likely to be forgotten.
Check Which AWS Profile and Account Are Active
Three checks answer different questions:
| Command | What it tells you |
|---|---|
echo "$AWS_PROFILE" |
Which profile name the shell selected through AWS_PROFILE |
aws configure list |
Where AWS CLI resolved the profile, credentials, and Region |
aws sts get-caller-identity |
Which AWS identity actually authenticated the API request |
Show the profile name the environment variable selected:
echo "$AWS_PROFILE"prodecho "$AWS_PROFILE" shows only the profile name selected through that environment variable. It does not prove which AWS identity will sign the next request.
Inspect how the CLI resolved settings:
aws configure listRead the TYPE and LOCATION columns for the access_key and secret_key rows. If the credential source shows env, exported environment variables are supplying the credentials even though the profile row says prod.
To verify which IAM user or role is authenticating the request:
aws sts get-caller-identity{
"UserId": "AIDAXXXXXXXXXXXXXXXXX",
"Account": "222222222222",
"Arn": "arn:aws:iam::222222222222:user/prod-admin"
}$AWS_PROFILE tells you which profile name was selected through the environment. get-caller-identity verifies the AWS account and IAM user or role that authenticated the request. Run it with the same --profile, AWS_PROFILE, and AWS_* environment variables as the command that follows — especially before terraform apply, aws s3 rm, or other destructive work.
To compare dev and prod in one shell, clear overrides first:
unset AWS_ACCESS_KEY_ID AWS_SECRET_ACCESS_KEY AWS_SESSION_TOKEN AWS_PROFILESwitch to dev and verify the account ID changes:
export AWS_PROFILE=devThe response should show the dev account:
aws sts get-caller-identity{
"UserId": "AIDAXXXXXXXXXXXXXXXXX",
"Account": "111111111111",
"Arn": "arn:aws:iam::111111111111:user/dev-admin"
}Switch to prod and verify again:
export AWS_PROFILE=prodThe account ID should move to production:
aws sts get-caller-identity{
"UserId": "AIDAXXXXXXXXXXXXXXXXX",
"Account": "222222222222",
"Arn": "arn:aws:iam::222222222222:user/prod-admin"
}When the Account matches but the Arn does not, the CLI is authenticated as a different IAM path than expected — common with role sessions and SSO permission sets. Read the full Arn, not only the 12-digit account ID. For a deeper provider walkthrough, see Which credentials AWS CLI uses.
How AWS CLI Profile and Credential Precedence Works
Selecting a profile and selecting credentials are two related steps. The profile tells AWS CLI which named configuration to use, while the credential provider determines how the CLI authenticates the request. Start with how the profile name was chosen:
How was the profile selected?
|
+--------------+--------------+
| | |
v v v
--profile prod AWS_PROFILE=prod neither
| | |
v v v
explicit profile shell-selected [default]
profile
| |
v v
credentials for credentials for
"prod" profile "prod" profile
(explicit (exported
profile) AWS_ACCESS_KEY_ID
can override file
keys in "prod")A profile is only a named configuration. The CLI still needs credentials to authenticate the request. Those credentials might come from access keys, IAM Identity Center, an assumed role, or another supported AWS credential provider.
--profile versus AWS_PROFILE
Both select a named profile, but they are not equivalent for every edge case.
Profile name precedence: --profile on the command line wins over AWS_PROFILE. If AWS_PROFILE=prod is set but the command includes --profile dev, the CLI explicitly uses the dev profile for that invocation.
Set the shell default to prod first:
export AWS_PROFILE=prodThen override it for one command with --profile dev:
aws sts get-caller-identity --profile dev{
"UserId": "AIDAXXXXXXXXXXXXXXXXX",
"Account": "111111111111",
"Arn": "arn:aws:iam::111111111111:user/dev-admin"
}The identity follows dev from --profile, not prod from the environment.
AWS_PROFILE versus exported credential variables
When the profile is selected through AWS_PROFILE, explicit credential environment variables can override credentials stored in that profile. AWS documents this case for environment variables such as AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY, and AWS_SESSION_TOKEN.
This pattern is different from passing --profile on the command line. An explicitly supplied CLI profile is a command-line setting; Botocore resolves credentials through the named profile's configured providers rather than treating exported access keys as an override of that explicit selection.
You normally would not mix a profile name from one account with exported credentials from another. That situation often happens unintentionally after a CI script, credential helper, or temporary shell setup exported AWS_ACCESS_KEY_ID and related variables.
Example with AWS_PROFILE only:
export AWS_PROFILE=devExport prod account keys on top of the dev profile name:
export AWS_ACCESS_KEY_ID=AKIAPRODKEYEXAMPLE
export AWS_SECRET_ACCESS_KEY='***'Check what the CLI will send:
aws configure listNAME : VALUE : TYPE : LOCATION
profile : dev : env : ['AWS_PROFILE', 'AWS_DEFAULT_PROFILE']
access_key : ****************5TGM : env :
secret_key : ****************Iwdx : env :
region : ap-south-1 : config-file : ~/.aws/configSTS signs the request with the exported keys, not the dev profile file:
aws sts get-caller-identity{
"UserId": "AIDAXXXXXXXXXXXXXXXXX",
"Account": "222222222222",
"Arn": "arn:aws:iam::222222222222:user/prod-admin"
}The profile row still says dev, but the Arn shows the prod user because environment keys override file-based credentials when the profile was selected through AWS_PROFILE. Clear overrides before trusting a profile switch:
unset AWS_ACCESS_KEY_ID AWS_SECRET_ACCESS_KEY AWS_SESSION_TOKENUse a Profile to Assume an IAM Role
A profile can assume an IAM role in another account or the same account. The config profile references a role_arn and a source_profile that holds credentials allowed to call sts:AssumeRole:
[profile audit]
region = ap-south-1
output = json
role_arn = arn:aws:iam::222222222222:role/audit-readonly
source_profile = prodThe prod profile must belong to an IAM user or role trusted by audit-readonly, and that identity needs sts:AssumeRole on the role ARN.
Think of source_profile as the identity AWS CLI starts with. Here, AWS CLI first authenticates using the prod profile, then uses that identity to request temporary credentials for the audit-readonly role. This example uses the existing prod identity to switch into a more restricted read-only role in the same account.
prod profile
|
| authenticate as the source identity
v
STS AssumeRole
|
| returns temporary credentials
v
audit-readonly roleCall the role profile like any other named profile:
aws sts get-caller-identity --profile audit{
"UserId": "AROAXXXXXXXXXXXXXXXXX:botocore-session-1790561406",
"Account": "222222222222",
"Arn": "arn:aws:sts::222222222222:assumed-role/audit-readonly/botocore-session-1790561406"
}The output confirms that the request is using an assumed-role session. The Arn contains assumed-role/audit-readonly/..., while UserId identifies the role session. get-caller-identity does not display the temporary access key, secret key, or session token — only identity metadata.
Run aws configure list --profile audit to inspect how the profile resolved its temporary credentials. For role and SSO profiles, AWS CLI can display the temporarily cached access key and secret key used for that session. The same verification step also works with SSO and other temporary credential methods: authenticate or refresh the credentials, then run aws sts get-caller-identity.
dev profile ──→ AWS account 111111111111
prod profile ──→ AWS account 222222222222
audit profile ──→ AssumeRole ──→ prod account (read-only role)Safely Switch Between AWS Accounts
Before production changes:
unset AWS_ACCESS_KEY_ID AWS_SECRET_ACCESS_KEY AWS_SESSION_TOKENwhen switching away from CI-style exports- Set
export AWS_PROFILE=<name>or pass--profileon the command - Run
aws sts get-caller-identityand readAccountandArn - Run
aws configure listif the identity still looks wrong — check LOCATION forenvversusshared-credentials-file
Terraform uses the same files but resolves credentials through the AWS provider. When terraform plan targets the wrong account, align AWS_PROFILE and any profile argument in the provider block — see Fix Terraform AWS credentials error.
Troubleshooting AWS CLI Profiles
| Symptom | Likely cause | Fix |
|---|---|---|
Wrong account despite AWS_PROFILE |
AWS_ACCESS_KEY_ID / AWS_SECRET_ACCESS_KEY exported |
unset env vars; re-run aws configure list |
--profile set but identity unexpected |
Role chain, SSO expiry, wrong config path, or custom credential process | aws configure list --profile <name> then aws sts get-caller-identity --profile <name> |
The config profile (x) could not be found |
Profile name is misspelled, or the profile section uses the wrong syntax — for example [x] instead of [profile x] in ~/.aws/config |
aws configure list-profiles; use [profile x] in config and [x] in credentials |
Role profile fails with AccessDenied on AssumeRole |
Missing trust or sts:AssumeRole on source identity |
Fix role trust policy and IAM policy on the source user |
InvalidClientTokenId after switching |
Stale keys in env or inactive access key | InvalidClientTokenId |
Unable to locate credentials |
Selected profile has no usable credentials, or no default credential source exists | Unable to locate credentials |
Summary
Named profiles let one workstation keep separate AWS CLI configurations for different accounts, roles, or authentication methods. Access-key profiles commonly use ~/.aws/credentials for credentials and ~/.aws/config for settings such as Region and role configuration. Use aws configure list-profiles to see valid names, --profile for a single command, and AWS_PROFILE for a session default.
If --profile and AWS_PROFILE specify different profiles, --profile takes precedence for that command. When a profile is selected with AWS_PROFILE, exported variables such as AWS_ACCESS_KEY_ID can still override credentials stored in that profile. Using an explicit --profile name tells AWS CLI to resolve credentials through that named profile for the command. Role profiles add role_arn and source_profile; the active principal shows as an assumed-role ARN after STS succeeds.
Make aws sts get-caller-identity part of every switch — read Account and the full Arn before destructive API calls. When keys are missing or rejected outright, use the dedicated troubleshooting guides for Unable to locate credentials and InvalidClientTokenId rather than guessing at profile names.
References
- AWS CLI — Authentication and access credentials
- AWS CLI — Configuration and credential file settings
- AWS CLI — Using profiles
- AWS CLI — Using an IAM role in the AWS CLI
- AWS CLI — IAM Identity Center authentication
- AWS CLI — Environment variables
- AWS STS — GetCallerIdentity
Frequently Asked Questions
Which wins: --profile or AWS_PROFILE?
--profile wins over AWS_PROFILE. For example, if AWS_PROFILE=prod is set but the command includes --profile dev, the CLI explicitly uses the dev profile for that invocation. Credential environment variables require a separate distinction: they can override credentials from a profile selected through AWS_PROFILE, while an explicitly supplied --profile causes the CLI to resolve credentials through that named profile.
Where are profile files stored?
By default the credentials file is ~/.aws/credentials and the config file is ~/.aws/config. Override paths with AWS_SHARED_CREDENTIALS_FILE and AWS_CONFIG_FILE. The credentials file holds access keys; the config file holds [profile name] sections with Region, output format, SSO settings, and role assumption settings.
Can profiles assume roles?
Yes. Add role_arn and source_profile to a [profile …] section in the config file. The CLI uses credentials from source_profile to call sts:AssumeRole and caches temporary keys for the role session. Verify with aws sts get-caller-identity --profile <role-profile> — the Arn contains assumed-role.

