Appearance
Get the public IP of a GitHub Actions runner
One step answers it: curl -s ipconfig.io inside the job prints the runner's egress IP — and the deeper answer is that on GitHub-hosted runners it's a fresh address from Azure's pool nearly every run, which is exactly why your IP-allowlisted database keeps rejecting deploys. Here's the diagnostic step, what the addresses actually are, and the patterns that beat chasing them.
Maintained by the ipconfig.io team · Reviewed 1 July 2026
The diagnostic step
yaml
jobs:
whoami:
runs-on: ubuntu-latest
steps:
- name: Runner egress IP
run: |
curl -s ipconfig.io
curl -s ipconfig.io/json # + asn_org, country: whose cloud, whereThe asn_org field will name Microsoft's network — GitHub-hosted runners are Azure VMs — and the country tells you which region your job landed in. Drop the step into a failing workflow right before the connection that's being refused, and you have the exact address your firewall saw (server-side logs and the runner's own reverse DNS corroborate).
Run it twice and you'll almost certainly see two different addresses. That's the model: each job is an ephemeral VM with pool egress. Nothing is wrong; nothing is stable either.
If you need to allowlist: the honest options
GitHub publishes its runner ranges at api.github.com/meta (the actions key):
bash
curl -s https://api.github.com/meta | jq -r '.actions[]' | headYou can feed those to a firewall, with two caveats that usually kill the idea: the list is thousands of broad Azure CIDRs (an allowlist that wide is closer to "allow the cloud"), and it changes over time, so it needs automated refresh. Where IP trust genuinely matters, the tighter patterns win:
| Option | What you get | Cost |
|---|---|---|
| Larger runners w/ static IP | GitHub-managed runners egressing from ranges dedicated to you | Paid GitHub feature |
| Self-hosted runner | Jobs egress from your own network — your address policy, your rules | You run the machine |
| Tunnel out, not in | The runner connects outbound to a bastion/tailnet/CF Tunnel; nothing inbound to allowlist | Setup once |
| Short-lived credentials (OIDC) | Auth by identity token instead of source address — the modern default for cloud deploys | Config, no infra |
The last row is the quiet best answer for most cloud targets: GitHub's OIDC tokens authenticate the workflow rather than trusting whatever VM it ran on, which is both tighter and immune to pool churn.
One etiquette note while you're wiring diagnostics: put the curl in a debug step you enable when needed, not a per-job fixture across a busy matrix — ephemeral runners multiplied by matrix builds add up fast, and a cached artifact of "what ranges is GitHub in" (api.github.com/meta) answers the standing question better than polling.
Frequently asked questions
Runner's public IP?curl -s ipconfig.io as a step. /json adds the ASN (Azure) and region.
Static? Not on standard hosted runners. Larger runners (paid) or self-hosted give you stability.
Allowlist GitHub's ranges? Published under actions at api.github.com/meta — broad and shifting; prefer static-IP runners, self-hosting, tunnels, or OIDC.
"IP not allowed" on deploy? Fresh VM, unlisted address — the ephemeral model. Switch trust from source IP to identity or tunnel.
Next steps
- Get a Docker container's public IP — the same question one layer down.
- Monitor your public IP for changes — the polite polling pattern for anything that watches addresses.
- What is reverse DNS? — reading who an address belongs to from the other side.