DevTools Hub

Search tools

Search for a developer tool

How to Parse an ARN in Python

Part of the AWS Toolkit
Pattern
partition, service, region, account_id, resource = arn.split(":", 5)[1:]

maxsplit=5 caps it at six pieces — the sixth absorbs every remaining colon, no rejoin needed

Explanation

An ARN has six colon-separated fields, but the resource field itself isn't guaranteed to be colon-free — a Lambda function version ARN packs a third piece into it:

arn:aws:lambda:us-east-1:123456789012:function:my-function:1

Plain arn.split(":") gives you eight elements here, not six, so indexing by position (parts[5]) grabs only "function" and silently drops my-function:1. Python's str.split has a cleaner fix built in than reaching for a rejoin: pass a maxsplit argument.

partition, service, region, account_id, resource = arn.split(":", 5)[1:]

maxsplit=5 caps the split at five colons, producing at most six elements — the sixth one absorbs everything left over, colons included, with no separate rejoin step needed the way a language without a maxsplit argument would require. Applied to the Lambda ARN above, the last element comes back as the full "function:my-function:1", untouched.

The same colons-in-the-resource trap applies to a hand-written regex. A pattern using ([^:]+) for every group looks reasonable, but [^:] explicitly excludes colons — that group won't match the Lambda ARN at all, not even partially. Use a greedy (.+) for the final group instead, since its job is to capture the rest of the string, colons included.

region and account_id can legitimately come back as empty strings, not missing — IAM and S3 ARNs omit one or both. Check == "", not is None, when deciding whether a field was actually provided; a present-but-empty field still shows up as an empty string from split.

For the same technique in JavaScript — where split has no maxsplit argument, so a rejoin is required instead — see How to Parse an ARN, or in Go or Java, see How to Parse an ARN in Go and How to Parse an ARN in Java for a similar count-based split with a sharper failure mode. For the full field-by-field breakdown of a specific ARN, see ARN Parser.

Valid examples

  • 'arn:aws:iam::123456789012:user/john'.split(':', 5) → ['arn', 'aws', 'iam', '', '123456789012', 'user/john']

    Only six pieces total — maxsplit doesn't change anything when there's nothing extra to protect.

  • 'arn:aws:lambda:us-east-1:123456789012:function:my-function:1'.split(':', 5) → [..., 'function:my-function:1']

    The last element absorbs both remaining colons instead of being cut off at the first one.

  • 'arn:aws:s3:::amzn-s3-demo-bucket/Development/*'.split(':', 5) → ['arn', 'aws', 's3', '', '', 'amzn-s3-demo-bucket/Development/*']

    region and account_id both come back as empty strings for an S3 bucket ARN — present, just empty.

Invalid examples

  • arn.split(':')[5] # 'function', not 'function:my-function:1'

    Splitting with no maxsplit and indexing by position — the Lambda ARN above has 8 parts, not 6, so [5] grabs the wrong piece.

  • re.match(r"^arn:([^:]+):([^:]+):([^:]*):([^:]*):([^:]+)$", arn)

    Every group uses [^:]+ — returns None for the Lambda ARN, since its resource part contains colons the pattern explicitly excludes.

  • if region is None: ...

    Checking for None instead of an empty string — split(':', 5) always returns a string for a present field, even an empty one, like IAM's region.

Try it now