Free IP API

A free REST API for IP addresses. Get the caller's own IP as plain text or JSON, or look up the location of any IPv4 or IPv6 address. Every endpoint answers with CORS and JSONP, so it works straight from a browser. No key, no sign-up.

Your IP address, as plain text

Returns the caller's public IP (IPv4 or IPv6) as plain text. Handy in shell scripts, or any time you need your external address.

EndpointDescription
https://api.ip.sb/ipAnswers on both IPv4 and IPv6
https://api-ipv4.ip.sb/ipIPv4 only
https://api-ipv6.ip.sb/ipIPv6 only

In a shell script

curl ip.sb        # both IPv4 and IPv6
curl ipv4.ip.sb   # IPv4 only  (same as: curl -4 ip.sb)
curl ipv6.ip.sb   # IPv6 only  (same as: curl -6 ip.sb)

#!/bin/sh
ip=$(curl -s https://api.ip.sb/ip -A My-User-Agent)
echo "My IP address is: $ip"

Sample output

192.0.2.2

or (on IPv6):

2001:db8::2

Code examples

Fetch your public IP from the plain-text endpoint. Most HTTP libraries send a default User-Agent that the edge blocks, so each example sets a custom one. Replace My-User-Agent with your own.

Python

import requests

r = requests.get("https://api.ip.sb/ip", headers={"User-Agent": "My-User-Agent"})
print("My public IP address is:", r.text.strip())

Ruby

require "net/http"

uri = URI("https://api.ip.sb/ip")
res = Net::HTTP.start(uri.host, uri.port, use_ssl: true) do |http|
  http.get(uri.path, "User-Agent" => "My-User-Agent")
end
puts "My public IP address is: #{res.body.strip}"

PHP

<?php
$context = stream_context_create(["http" => ["header" => "User-Agent: My-User-Agent"]]);
$ip = file_get_contents("https://api.ip.sb/ip", false, $context);
echo "My public IP address is: " . trim($ip);

Java

import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;

public class Main {
    public static void main(String[] args) throws Exception {
        var client = HttpClient.newHttpClient();
        var request = HttpRequest.newBuilder(URI.create("https://api.ip.sb/ip"))
                .header("User-Agent", "My-User-Agent")
                .build();
        var ip = client.send(request, HttpResponse.BodyHandlers.ofString()).body();
        System.out.println("My public IP address is: " + ip.strip());
    }
}

Perl

use strict;
use warnings;
use LWP::UserAgent;

my $ua = LWP::UserAgent->new(agent => "My-User-Agent");
my $ip = $ua->get("https://api.ip.sb/ip")->decoded_content;
print "My public IP address is: $ip";

C#

using var client = new HttpClient();
client.DefaultRequestHeaders.UserAgent.ParseAdd("My-User-Agent");
string ip = (await client.GetStringAsync("https://api.ip.sb/ip")).Trim();
Console.WriteLine($"My public IP address is: {ip}");

Node.js

const https = require("https");

const options = { headers: { "User-Agent": "My-User-Agent" } };
https.get("https://api.ip.sb/ip", options, (res) => {
  let ip = "";
  res.on("data", (chunk) => (ip += chunk));
  res.on("end", () => console.log("My public IP address is:", ip.trim()));
});

Go

package main

import (
	"io"
	"net/http"
	"os"
)

func main() {
	req, _ := http.NewRequest("GET", "https://api.ip.sb/ip", nil)
	req.Header.Set("User-Agent", "My-User-Agent")
	res, _ := http.DefaultClient.Do(req)
	defer res.Body.Close()
	io.Copy(os.Stdout, res.Body)
}

Rust

// Cargo.toml: reqwest = { version = "0.13.4", features = ["blocking"] }
use reqwest::blocking::Client;

fn main() -> Result<(), Box<dyn std::error::Error>> {
    let ip = Client::new()
        .get("https://api.ip.sb/ip")
        .header("User-Agent", "My-User-Agent")
        .send()?
        .text()?;
    println!("My public IP address is: {}", ip.trim());
    Ok(())
}

Your IP address, as JSON

The same address wrapped in a JSON object. Add a callback parameter to get JSONP instead.

Usage

<script src="https://api.ip.sb/jsonip?callback=getip"></script>
<script>
function getip(json) {
  console.log("My IP address is", json.ip);
}
</script>

Geolocation, as JSON

Call /geoip with no argument to locate the caller's own IP:

Append any IP address to the path to locate that one instead:

Usage

<script src="https://api.ip.sb/geoip?callback=getgeoip"></script>
<script>
function getgeoip(json) {
  console.log(json.country, json.latitude, json.longitude);
}
</script>

Response fields

Not every field is known for every IP. Anything missing is left out of the response rather than returned empty.

FieldDescription
ipCaller IP, or the IP you asked about
country_codeTwo-letter ISO 3166-1 alpha-2 country code
countryCountry name
region_codeState or region code (ISO 3166-2 for the US and Canada, FIPS 10-4 elsewhere)
regionRegion name
cityCity name
postal_codePostal or ZIP code
continent_codeTwo-letter continent code
latitudeLatitude
longitudeLongitude
timezoneTime zone
offsetUTC offset in seconds
asnAutonomous System Number
asn_organizationOrganization that holds the ASN
ispISP name
organizationOrganization name

Sample output

Example response:

{
  "region": "New York",
  "organization": "iCloud Private Relay",
  "region_code": "NY",
  "isp": "iCloud Private Relay",
  "city": "New York",
  "asn_organization": "Akamai Technologies, Inc.",
  "postal_code": "10118",
  "asn": 36183,
  "latitude": 40.7126,
  "ip": "172.225.7.7",
  "continent_code": "NA",
  "offset": -18000,
  "country": "United States",
  "timezone": "America/New_York",
  "country_code": "US",
  "longitude": -74.0066
}

Errors

Invalid input returns HTTP 400 (Bad Request) with a JSON error body.

HTTPCodeMessage
400401Input string is not a valid IP address

Rate limits

The free API allows 100 requests per minute per IP address (up to 5 per second), which is plenty for personal projects and light integrations. If you need a higher limit, an API key, or you are shipping a commercial product, take a look at our plans or get in touch for a custom setup.

Credits

Geolocation data comes from MaxMind GeoIP.