boto3
S3
AWS
credentials
Python

How to specify credentials when connecting to boto3 S3?

System Design practice on Codemia

Work through 120+ system design problems with detailed solutions, from rate limiters to multi-region storage.

Practice system design

Introduction

When you create a Boto3 S3 client, you usually do not pass raw credentials directly in code. Boto3 already knows how to search for credentials through AWS's provider chain, so the real question is which source you want it to use and when you should override the default behavior.

How Boto3 Finds Credentials

Boto3 looks for AWS credentials in a defined order, with some sources preferred over others. In practice, the most common choices are:

  • An IAM role attached to the compute environment
  • Environment variables
  • A named profile in ~/.aws/credentials
  • Explicit credentials in code

You can often let Boto3 resolve credentials automatically:

python
1import boto3
2
3s3 = boto3.client("s3", region_name="us-east-1")
4print(s3.list_buckets())

That works when valid credentials already exist somewhere in the provider chain.

Option 1: Environment Variables

Environment variables are a simple way to supply credentials locally or in short-lived automation.

bash
export AWS_ACCESS_KEY_ID=AKIA...
export AWS_SECRET_ACCESS_KEY=...
export AWS_REGION=us-east-1

Then your Python code can stay minimal:

python
1import boto3
2
3s3 = boto3.client("s3")
4for bucket in s3.list_buckets()["Buckets"]:
5    print(bucket["Name"])

This is easy to set up, but it also makes accidental credential leakage easier if shells, logs, or process environments are not handled carefully.

Option 2: Shared AWS Credentials Profile

For local development, a named profile is usually cleaner than exporting keys over and over.

Example ~/.aws/credentials:

ini
[dev]
aws_access_key_id = AKIA...
aws_secret_access_key = ...

Python code:

python
1import boto3
2
3session = boto3.Session(profile_name="dev", region_name="us-east-1")
4s3 = session.client("s3")
5
6print(s3.list_objects_v2(Bucket="my-bucket", MaxKeys=5))

Profiles are especially useful when you switch between accounts or roles regularly.

Option 3: Temporary Credentials

If you use STS or a federated login flow, you may also need a session token. In that case, include all three credential values.

python
1import boto3
2
3s3 = boto3.client(
4    "s3",
5    aws_access_key_id="ASIA...",
6    aws_secret_access_key="...",
7    aws_session_token="...",
8    region_name="us-east-1",
9)

Temporary credentials are common in secure environments because they expire automatically, which reduces the blast radius of leaked secrets.

Option 4: IAM Role on AWS Infrastructure

If your code runs on EC2, ECS, EKS, or Lambda, the best practice is usually to attach an IAM role and let Boto3 fetch credentials automatically.

python
1import boto3
2
3def upload_file(path: str, bucket: str, key: str) -> None:
4    s3 = boto3.client("s3")
5    s3.upload_file(path, bucket, key)

No hardcoded secrets are needed, and credential rotation is handled by AWS. This is the preferred production path for most AWS-hosted workloads.

When Explicit Credentials in Code Make Sense

Passing credentials directly to boto3.client is usually a last resort. It can be acceptable for a short-lived local script or a controlled test, but it is not a good default for long-lived application code.

If you must do it, avoid committing secrets to source control and keep the values outside the code file itself, such as in a secret manager or temporary environment injection.

That keeps the code path explicit without normalizing insecure habits across the project.

Common Pitfalls

  • Forgetting region_name can trigger NoRegionError even when the credentials are valid.
  • Using temporary credentials without aws_session_token causes confusing authentication failures.
  • Mixing environment variables, profiles, and explicit session configuration can lead to "wrong account" problems when Boto3 chooses a different source than you expected.
  • Hardcoding long-lived credentials into application code creates unnecessary security risk.

Summary

  • Prefer the default AWS credential provider chain instead of hardcoding secrets.
  • Use profiles or environment variables for local development.
  • Use IAM roles for AWS-hosted production workloads.
  • Include a session token when working with temporary credentials.

Related reading
Course
Beginner
27 lessons
10 hours
System Design Fundamentals

Build a strong foundation in designing scalable, reliable distributed systems.

View the course
Track what you have practised

A free account saves your progress, solutions and study plan across every problem on Codemia.

System Design practice on Codemia

Work through 120+ system design problems with detailed solutions, from rate limiters to multi-region storage.

Practice system design

All Rights Reserved.