API Documentation

Developer Guide for MyIP.foo API - Free, Fast, No Authentication Required

MyIP.foo provides a simple, free API for retrieving IP address information. No API key or registration required. Perfect for scripts, CI/CD pipelines, VPN verification, and network monitoring.

Quick Start

GET https://myip.foo/plain

Returns your IP address as plain text (IPv4 or IPv6)

Try it now
GET https://myip.foo/api

Returns comprehensive IP data as JSON (geolocation, ISP, network info)

Try it now

Endpoints

/plain - Plain Text IP

Returns only your IP address as plain text. Perfect for shell scripts and CLI usage.

Bash / curl
# Get your IP address
curl https://myip.foo/plain

# Save to variable
MY_IP=$(curl -s https://myip.foo/plain)
echo "My IP: $MY_IP"

# Force IPv4
curl -4 https://myip.foo/plain

# Force IPv6
curl -6 https://myip.foo/plain

/api - JSON API

Returns comprehensive IP information in JSON format including geolocation, ISP, ASN, and Cloudflare datacenter location.

Response Format
{
  "ip": "2001:db8::1",
  "type": "IPv6",
  "hostname": "example.kpn.net",
  "connectionType": "residential",
  "location": {
    "country": "NL",
    "city": "Amsterdam",
    "region": "North Holland",
    "postalCode": "1012",
    "timezone": "Europe/Amsterdam",
    "latitude": "52.3740",
    "longitude": "4.8897"
  },
  "network": {
    "asn": 1136,
    "isp": "KPN B.V."
  },
  "client": {
    "browser": "Chrome 120",
    "platform": "macOS"
  },
  "cloudflare": {
    "colo": "AMS",
    "ray": "7d4f1a2b3c4d5e6f-AMS"
  }
}

/api/connection-type - Connection Detection Only

Returns only the connection type classification (VPN/Datacenter/Residential) without full geolocation data. Useful for lightweight VPN verification.

Bash / curl
# Check connection type
curl https://myip.foo/api/connection-type
Response Format
{
  "type": "residential",
  "ip": "203.0.113.45"
}

Connection Types:

/headers - HTTP Request Headers

Returns all HTTP request headers received by the server. Useful for debugging, checking proxy configurations, or testing custom headers.

Bash / curl
# View all request headers
curl https://myip.foo/headers

# Add custom headers for testing
curl -H "X-Custom-Header: test" https://myip.foo/headers
Response Format
{
  "accept": "*/*",
  "user-agent": "curl/8.1.2",
  "cf-connecting-ip": "203.0.113.45",
  "cf-ipcountry": "NL",
  "cf-ray": "7d4f1a2b3c4d5e6f-AMS",
  "cf-visitor": "{\"scheme\":\"https\"}",
  "x-forwarded-proto": "https",
  "x-real-ip": "203.0.113.45",
  "host": "myip.foo"
}

/user-agent - User Agent Parsing

Parses your User-Agent string and returns detailed information about your browser, operating system, and device type.

Bash / curl
# Parse your user agent
curl https://myip.foo/user-agent
Response Format
{
  "userAgent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36",
  "browser": {
    "name": "Google Chrome",
    "version": "120.0.0.0"
  },
  "os": {
    "name": "macOS",
    "version": "10.15.7"
  },
  "device": "desktop",
  "cloudflare": {
    "deviceType": "desktop",
    "country": "NL"
  }
}

Supported Browsers: Chrome, Firefox, Safari, Edge, Opera

Supported OS: Windows, macOS, Linux, Android, iOS

Device Types: desktop, mobile, tablet

Dual-Stack Detection (IPv4 + IPv6)

This is a common question from dual-stack users (those with both IPv4 and IPv6 connectivity):

Server-Side Limitation: When you make a request to https://myip.foo/api, your browser/client chooses one protocol (IPv4 or IPv6) to connect. The server only sees the IP of that connection, not both.

Browser Behavior: Modern browsers prefer IPv6 when available (RFC 6555 "Happy Eyeballs"). So on dual-stack networks, /api typically shows your IPv6 address.

Solutions for Dual-Stack Detection:

Note: Protocol-specific subdomains are not supported due to Cloudflare's dual-stack proxy infrastructure, which always provides both IPv4 and IPv6 connectivity regardless of DNS records.

Why can't the server detect both? It's technically impossible. The server can only see the connection you made. To get both IPs, you'd need to make two separate connections (one IPv4, one IPv6) or use client-side techniques like WebRTC.

Dual-Stack Detection Examples

Bash / Shell Script
#!/bin/bash
# dual-stack-check.sh - Check both IPv4 and IPv6 addresses

echo "Checking dual-stack connectivity..."

# Check IPv4 with curl -4 flag
IPV4=$(curl -4 -s https://myip.foo/plain 2>/dev/null)
if [ $? -eq 0 ]; then
  echo "✓ IPv4: $IPV4"
else
  echo "✗ IPv4: Not available"
fi

# Check IPv6 with curl -6 flag
IPV6=$(curl -6 -s https://myip.foo/plain 2>/dev/null)
if [ $? -eq 0 ]; then
  echo "✓ IPv6: $IPV6"
else
  echo "✗ IPv6: Not available"
fi
Python - Get Both IPv4 and IPv6
import subprocess
import json

# Get IPv4 address using curl -4
try:
    ipv4_result = subprocess.run(
        ['curl', '-4', '-s', 'https://myip.foo/api'],
        capture_output=True, text=True, timeout=5
    )
    ipv4_data = json.loads(ipv4_result.stdout)
    print(f"IPv4: {ipv4_data['ip']} ({ipv4_data['location']['city']})")
except Exception as e:
    print(f"IPv4: Not available ({e})")

# Get IPv6 address using curl -6
try:
    ipv6_result = subprocess.run(
        ['curl', '-6', '-s', 'https://myip.foo/api'],
        capture_output=True, text=True, timeout=5
    )
    ipv6_data = json.loads(ipv6_result.stdout)
    print(f"IPv6: {ipv6_data['ip']} ({ipv6_data['location']['city']})")
except Exception as e:
    print(f"IPv6: Not available ({e})")

Code Examples

Python

Python
import requests

# Get IP as string
ip = requests.get('https://myip.foo/plain').text.strip()
print(f"My IP: {ip}")

# Get full data
data = requests.get('https://myip.foo/api').json()
print(f"IP: {data['ip']}")
print(f"Country: {data['location']['country']}")
print(f"City: {data['location']['city']}")
print(f"ISP: {data['network']['isp']}")

JavaScript / Node.js

JavaScript
// Using fetch (Node.js 18+)
const response = await fetch('https://myip.foo/api');
const data = await response.json();

console.log(`IP: ${data.ip}`);
console.log(`Location: ${data.location.city}, ${data.location.country}`);
console.log(`ISP: ${data.network.isp}`);

// Plain text
const ip = await fetch('https://myip.foo/plain').then(r => r.text());
console.log(`My IP: ${ip.trim()}`);

PHP

PHP
<?php
// Get IP as string
$ip = file_get_contents('https://myip.foo/plain');
echo "My IP: " . trim($ip);

// Get JSON data
$data = json_decode(file_get_contents('https://myip.foo/api'), true);
echo "IP: " . $data['ip'] . "\n";
echo "Country: " . $data['location']['country'] . "\n";
echo "City: " . $data['location']['city'] . "\n";

Go

Go
package main

import (
    "encoding/json"
    "fmt"
    "io"
    "net/http"
)

type IPData struct {
    IP       string `json:"ip"`
    Location struct {
        Country string `json:"country"`
        City    string `json:"city"`
    } `json:"location"`
}

func main() {
    // Plain text
    resp, _ := http.Get("https://myip.foo/plain")
    body, _ := io.ReadAll(resp.Body)
    fmt.Printf("My IP: %s\n", string(body))

    // JSON
    resp, _ = http.Get("https://myip.foo/api")
    var data IPData
    json.NewDecoder(resp.Body).Decode(&data)
    fmt.Printf("%s from %s, %s\n", data.IP, data.Location.City, data.Location.Country)
}

Use Cases

Shell Script - IP Change Monitor

Bash
#!/bin/bash
# check-ip.sh - Monitor IP changes

IP_FILE="/tmp/current_ip.txt"
CURRENT_IP=$(curl -s https://myip.foo/plain)

if [ -f "$IP_FILE" ]; then
  OLD_IP=$(cat "$IP_FILE")
  if [ "$OLD_IP" != "$CURRENT_IP" ]; then
    echo "IP changed: $OLD_IP → $CURRENT_IP"
    # Send notification here
  fi
fi

echo "$CURRENT_IP" > "$IP_FILE"

GitHub Actions - Get Runner IP

YAML
name: Check Runner IP
on: [push]
jobs:
  check-ip:
    runs-on: ubuntu-latest
    steps:
      - name: Get GitHub Actions runner IP
        run: |
          IP=$(curl -s https://myip.foo/plain)
          echo "Runner IP: $IP"
          curl -s https://myip.foo/api | jq '.'

Docker Healthcheck

Dockerfile
HEALTHCHECK --interval=30s --timeout=3s \
  CMD curl -f https://myip.foo/plain || exit 1

VPN Verification Script

Python
import requests

def check_vpn_status():
    data = requests.get('https://myip.foo/api').json()

    # Check if IP is in expected VPN country
    expected_country = "NL"  # Netherlands
    actual_country = data['location']['country']

    if actual_country == expected_country:
        print(f"✅ VPN active: {data['ip']} ({data['location']['city']}, {actual_country})")
    else:
        print(f"⚠️  VPN inactive or wrong location: {actual_country}")

check_vpn_status()

Usage

Fair Use Policy

MyIP.foo is provided as a free public service. We ask that you use it responsibly:

For high-volume commercial usage or custom needs, contact us for enterprise support.

Response Fields

IP Information

Location Data

Network Information

Client Information

Cloudflare Metadata

Data Accuracy

Geolocation data is provided by Cloudflare's IP geolocation database and is typically accurate at the city level (within 50-100 miles). ISP and network information (ASN) is highly accurate.

Privacy

See our Privacy Policy for full details.

More Examples

Find more code examples and integration guides on our GitHub repository.

Support

Having issues or questions? Contact us at [email protected] or open an issue on GitHub.

Ready to get started?

Try the API right now:

Open JSON API Open Plain Text