Sometimes it’s necessary to get the list of EC2 stopped instances across different AWS accounts to see how many instances have been stopped. There might be variety of reasons why we may need to see the list of stopped EC2 instances (like whether those instances can be terminated or whether those instances needed to be started to be patched etc.,)
Account wise Stopped instances
First we may need to get the list of accounts and then iterate through each accounts by assuming a specific role to get the list of stopped instances
import boto3
import csv
ROLE_NAME = "CrossAccountEC2ReadRole"
# Get all accounts from AWS Organizations
org_client = boto3.client('organizations')
accounts = []
paginator = org_client.get_paginator('list_accounts')
for page in paginator.paginate():
for acct in page['Accounts']:
if acct['Status'] == 'ACTIVE':
accounts.append(acct['Id'])
# Get all AWS regions
ec2_client = boto3.client('ec2')
regions = [r['RegionName'] for r in ec2_client.describe_regions()['Regions']]
# Prepare to collect stopped instances
all_stopped_instances = []
# Iterate through each account and region
for account_id in accounts:
try:
sts_client = boto3.client('sts')
role_arn = f"arn:aws:iam::{account_id}:role/{ROLE_NAME}"
response = sts_client.assume_role(
RoleArn=role_arn,
RoleSessionName='ListStoppedInstancesSession'
)
creds = response['Credentials']
session = boto3.Session(
aws_access_key_id=creds['AccessKeyId'],
aws_secret_access_key=creds['SecretAccessKey'],
aws_session_token=creds['SessionToken']
)
for region in regions:
ec2 = session.client('ec2', region_name=region)
response = ec2.describe_instances(
Filters=[{'Name': 'instance-state-name', 'Values': ['stopped']}]
)
for reservation in response['Reservations']:
for instance in reservation['Instances']:
all_stopped_instances.append([
account_id,
region,
instance['InstanceId']
])
except Exception as e:
print(f"Error accessing account {account_id}: {e}")
# Write to CSV
with open('allstopped_instances.csv', mode='w', newline='') as file:
writer = csv.writer(file)
writer.writerow(['AccountId', 'Region', 'InstanceId']) # Header
writer.writerows(all_stopped_instances)
print(f"✅ Done! {len(all_stopped_instances)} stopped instances written to 'allstopped_instances.csv'")
Single Account Stopped instances
The below script gets the list of stopped instances for a single account for all the regions
import boto3
import csv
# Get all AWS regions
ec2_client = boto3.client('ec2')
regions = [r['RegionName'] for r in ec2_client.describe_regions()['Regions']]
# Collect stopped instances
stopped_instances = []
for region in regions:
ec2 = boto3.client('ec2', region_name=region)
response = ec2.describe_instances(
Filters=[{'Name': 'instance-state-name', 'Values': ['stopped']}]
)
for reservation in response['Reservations']:
for instance in reservation['Instances']:
stopped_instances.append([
region,
instance['InstanceId']
])
# Write to CSV
with open('stopped_instances.csv', mode='w', newline='') as file:
writer = csv.writer(file)
writer.writerow(['Region', 'InstanceId']) # Header
writer.writerows(stopped_instances)
print(f"✅ Done! {len(stopped_instances)} stopped instances written to 'stopped_instances.csv'")