DevTools Hub

Search tools

Search for a developer tool

How to Parse an ARN

Part of the AWS Toolkit
Pattern
const [, partition, service, region, accountId, ...rest] = arn.split(":");

the resource is rest.join(":") — everything after the fifth colon, since the resource itself can contain colons

Explanation

An ARN looks like six colon-separated fields, so the obvious first instinct is arn.split(":") and grabbing indices by position. That works for the first four fields — but breaks on the fifth, because the resource part isn't guaranteed to be colon-free. A Lambda function version ARN, for example, packs a third piece into the resource itself:

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

Split that on every colon and you get eight parts, not six — [5] alone is just "function", silently dropping my-function:1. The fix is to destructure the first five fields by position, then rejoin everything left over:

const [, partition, service, region, accountId, ...rest] = arn.split(":");
const resource = rest.join(":");

The leading empty slot in the destructure absorbs the string before the first colon (always the literal "arn", which you can validate separately if you want). rest collects everything from the sixth field onward as an array — for a simple ARN that's just one element, but for the Lambda case above it's ["function", "my-function", "1"], and .join(":") puts it back together exactly as it appeared.

The same trap applies to a hand-written regex: a pattern like ([^:]+) for the resource 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 it's meant to capture the rest of the string, colons included.

region and accountId can legitimately be empty strings, not missing — IAM and S3 ARNs omit one or both. Check for an empty string, not undefined, when deciding whether a field was actually provided.

For the full field-by-field breakdown of a specific ARN — including the resource-type/ID split and warnings for a malformed account ID — see ARN Parser. For what each field means and why the format looks like this, see What Is an ARN? For the same technique in Python — where str.split takes a maxsplit argument directly, so no rejoin is needed — see How to Parse an ARN in Python, or in Go, where a similar count argument exists but a slice index past the end panics instead of returning undefined, see How to Parse an ARN in Go. Java uses the same convention as Go — see How to Parse an ARN in Java.

Valid examples

  • "arn:aws:iam::123456789012:user/john" → resource: "user/john"

    Only one field after the fifth colon — rest.join(":") returns it unchanged.

  • "arn:aws:lambda:us-east-1:123456789012:function:my-function:1" → resource: "function:my-function:1"

    Three fields after the fifth colon — rejoined correctly instead of truncated.

  • "arn:aws:s3:::amzn-s3-demo-bucket/Development/*" → region: "", accountId: ""

    Both fields legitimately empty strings for an S3 bucket ARN — still present as fields, not missing.

Invalid examples

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

    Grabbing a single index instead of joining the remainder — silently drops everything after the sixth colon-separated piece.

  • /^arn:([^:]+):([^:]+):([^:]*):([^:]*):([^:]+)$/

    Every group uses [^:]+ — the Lambda ARN above fails to match at all, since its resource part contains colons the pattern explicitly excludes.

  • if (region === undefined) { /* ... */ }

    Checking for undefined instead of an empty string — split(":") always returns a string for a present field, even when that field is empty, like IAM's region.

Try it now