Choosing the right interface determines how you read the AWS docs and how future-proof your code is.
boto3 offers two interfaces.
A client (boto3.client("s3")) maps one-to-one onto the service API: every AWS operation is a method in snake_case (ListBuckets becomes list_buckets), parameters are keyword arguments with the API's exact names (Bucket=, Key=), and responses are plain dicts mirroring the API's JSON, plus a ResponseMetadata entry with the HTTP status and request id. Every service and every operation is available, as soon as AWS releases it.
A resource (boto3.resource("s3")) is an object-oriented layer: s3.Bucket("name").objects.all() yields ObjectSummary objects with attributes, and collections paginate automatically. It's pleasant, but only some services have resources (S3, DynamoDB, EC2, SQS, IAM and a few others), and AWS has stated that no new features will be added to resources. New code should generally use clients; the resource API remains fine where it's already used, notably DynamoDB's Table object.
You can reach the client behind a resource with resource.meta.client.
Reading the docs: each service's client reference lists every method with request syntax and response structure. Tools like boto3-stubs (mypy-boto3) add type hints and editor autocompletion for those dicts.
Create clients once and reuse them: creating one loads the service model and costs real time.
Example
import boto3
s3 = boto3.client("s3", region_name="us-east-1")
s3.create_bucket(Bucket="demo-reports-2026")
s3.put_object(Bucket="demo-reports-2026", Key="a.txt", Body=b"hello")
# Client: API operations, dict responses
resp = s3.list_objects_v2(Bucket="demo-reports-2026")
print(resp["ResponseMetadata"]["HTTPStatusCode"]) # 200
print([o["Key"] for o in resp.get("Contents", [])]) # ['a.txt']
# Resource: objects and collections (feature-frozen interface)
bucket = boto3.resource("s3", region_name="us-east-1").Bucket("demo-reports-2026")
for obj in bucket.objects.all():
print(obj.key, obj.size) # a.txt 5
print(bucket.meta.client.meta.service_model.service_name) # s3Remember
- Clients: one method per API operation, dict in and dict out
- Resources: object-oriented, but limited to some services and feature-frozen
- Prefer clients for new code; DynamoDB's Table resource is still common
- Create clients once and reuse them
Watch out for
- Calling boto3.client(...) inside a hot loop for every request.