boto3 Basics
10 examples to get you started with Cloud SDKs - 7 basic and 3 intermediate.
Prerequisites
uv venv && source .venv/bin/activate
uv pip install "boto3>=1.35"
aws configure --profile dev # or export AWS_PROFILE=dev- Python 3.14.0 with boto3 installed in a venv.
- AWS credentials via
~/.aws/credentials, environment variables, or instance/task IAM role.
Basic Examples
1. Create a Session
boto3.Session is the entry point for region, profile, and credential resolution.
import boto3
session = boto3.Session(profile_name="dev", region_name="us-east-1")
print(session.region_name)- One session per logical AWS account/region context in scripts.
profile_namemaps to~/.aws/credentialssections.- Prefer explicit
region_name- global clients still need a signing region.
Related: Credential & Session Patterns - least privilege setups
2. Low-Level Client
Clients expose the raw AWS API - one method per API action.
import boto3
s3 = boto3.client("s3")
resp = s3.list_buckets()
print([b["Name"] for b in resp.get("Buckets", [])])- Clients return plain dicts matching AWS API shapes.
- Pagination is manual unless you use paginators (see intermediate examples).
- Best for full API coverage and newest operations.
Related: S3 - uploads, downloads, presigned URLs
3. Resource Interface
Resources provide an object-oriented layer over clients.
import boto3
s3 = boto3.resource("s3")
for bucket in s3.buckets.all():
print(bucket.name)Bucket,Object,Tableclasses wrap common workflows.- Not every API operation has a resource equivalent - fall back to clients when needed.
- Resources still use the same credential chain as clients.
Related: S3 - streaming and object operations
4. Region and Endpoint Configuration
Pin region to avoid surprising cross-region latency or wrong partition behavior.
import boto3
session = boto3.Session(region_name="eu-west-1")
dynamodb = session.client("dynamodb")
print(dynamodb.meta.region_name)meta.region_nameconfirms where requests sign.- Use
endpoint_urlonly for LocalStack, VPC endpoints, or custom gateways. - Multi-region apps create one session per region, not one global client.
Related: Retry, Pagination & Throttling - robust calls at scale
5. Credential Chain Order
boto3 resolves credentials automatically when you do not pass keys in code.
import boto3
session = boto3.Session()
creds = session.get_credentials()
print(creds.method if creds else "no credentials")- Order: env vars → shared config/credentials → IAM role (EC2/ECS/Lambda).
AWS_PROFILEselects a named profile without hardcoding in source.- Never commit access keys - rotate immediately if leaked.
Related: Secrets Manager & SSM - runtime secret fetch
6. Error Handling with ClientError
AWS errors arrive as botocore.exceptions.ClientError with structured codes.
import boto3
from botocore.exceptions import ClientError
s3 = boto3.client("s3")
try:
s3.head_bucket(Bucket="definitely-missing-bucket-xyz")
except ClientError as exc:
code = exc.response["Error"]["Code"]
print(code)- Branch on
Error.Code(404,NoSuchBucket,AccessDenied) not message strings. responsedict mirrors AWS XML/JSON error payloads.- Log request ID from
ResponseMetadatafor AWS support tickets.
Related: Cloud SDK Best Practices - safe error handling rules
7. Reuse Clients in Workers
Create clients once per process, not per request in hot loops.
import boto3
_SESSION = boto3.Session()
_SQS = _SESSION.client("sqs")
def send_message(queue_url: str, body: str) -> None:
_SQS.send_message(QueueUrl=queue_url, MessageBody=body)- Client creation is relatively expensive; module-level reuse is fine for scripts and workers.
- Thread safety: clients are generally thread-safe; resources are not always.
- In Lambda, create clients outside the handler for connection reuse across invocations.
Related: SQS & SNS - queue and topic patterns
Intermediate Examples
8. Paginators for Large Result Sets
Stop hand-rolling NextToken loops - use built-in paginators.
import boto3
s3 = boto3.client("s3")
paginator = s3.get_paginator("list_objects_v2")
for page in paginator.paginate(Bucket="my-bucket", Prefix="logs/"):
for obj in page.get("Contents", []):
print(obj["Key"], obj["Size"])- Paginators handle tokens and page sizes consistently.
- Set
PaginationConfig={"MaxItems": 100}to cap dev scripts. - Pair with Retry, Pagination & Throttling for throttled APIs.
Related: DynamoDB - query pagination
9. Waiters for Resource Convergence
Wait until AWS finishes asynchronous creation before dependent steps.
import boto3
ec2 = boto3.client("ec2")
waiter = ec2.get_waiter("instance_running")
instance_id = "i-0123456789abcdef0"
waiter.wait(InstanceIds=[instance_id])- Waiters poll with backoff until success or max attempts.
- Prefer waiters over
time.sleepguesses in provisioning scripts. - Configure
WaiterConfig={"Delay": 5, "MaxAttempts": 40}for long-running resources.
Related: Provisioning Cloud Resources - bootstrap workflows
10. botocore Config for Retries and Timeouts
Tune retries and timeouts for production traffic patterns.
import boto3
from botocore.config import Config
config = Config(
retries={"max_attempts": 10, "mode": "standard"},
connect_timeout=5,
read_timeout=60,
)
s3 = boto3.client("s3", config=config)mode: adaptivehelps under sustained throttling;standardis predictable default.- Separate connect vs read timeouts - large S3 downloads need higher read timeout.
- Apply the same
Configobject to every client in a service class.
Related: Retry, Pagination & Throttling - throttling strategies
Stack versions: This page was written for Python 3.14.0 (stable 3.14, maintenance 3.13), FastAPI 0.115+, Django 5.2, Flask 3.1, Pydantic 2, PyTorch 2.6+, pandas 2.2+, Polars 1.x, ruff 0.9+, and uv 0.6+.