Every time I start a new side project, I find myself reaching for the same handful of free public APIs. They require no API key, have generous rate limits, and handle tasks that would take days to build from scratch.
Here are 6 that I use regularly. All of them are free, HTTPS, and work directly from the browser.
## 1. IPify - Get the Client's IP Address
The problem: you cannot get a visitor's public IP address from JavaScript alone. The browser doesn't expose it.
IPify solves this with a simple endpoint:
https://api.ipify.org?format=json
It returns:
json
{ "ip": "203.0.113.47" }
If you need IPv6, use `api64.ipify.org` instead. It returns IPv6 when the client supports it, and falls back to IPv4 otherwise.
javascript
fetch('https://api.ipify.org?format=json')
.then(res => res.json())
.then(data => console.log('Your IP:', data.ip));
What I use it for: analytics dashboards, security logging, and any time I need to identify a connection's network origin.
## 2. ipapi.co - IP Geolocation
Once you have the IP, ipapi.co tells you roughly where it is:
plaintext
https://ipapi.co/json/
The response includes city, region, country, timezone, coordinates, and the ISP:
json
{
"ip": "203.0.113.47",
"city": "London",
"region": "England",
"country_name": "United Kingdom",
"latitude": 51.5085,
"longitude": -0.1257,
"org": "Example ISP"
}
The free tier allows 1,000 requests per day without an API key.
javascript
fetch('https://ipapi.co/json/')
.then(res => res.json())
.then(data => {
console.log(You appear to be in ${data.city}, ${data.country_name});
});
One important note: IP geolocation is approximate. It might point to a data center 200 km away. Never present these coordinates as the user's exact location.
## 3. Have I Been Pwned - Password Breach Check
This one is brilliant. HIBP lets you check if a password has appeared in known data breaches, using a technique called k-anonymity.
Here is how it works. You hash the password with SHA-1 in the browser. Then you send only the first 5 characters of the hash to the API. The API returns all hashes that share that prefix, and you check locally if the full hash is in the list.
The password never leaves the browser. The server never sees the full hash.
javascript
async function checkPassword(password) {
const buffer = new TextEncoder().encode(password);
const hashBuffer = await crypto.subtle.digest('SHA-1', buffer);
const hash = Array.from(new Uint8Array(hashBuffer))
.map(b => b.toString(16).padStart(2, '0'))
.join('')
.toUpperCase();
const prefix = hash.substring(0, 5);
const suffix = hash.substring(5);
const res = await fetch(https://api.pwnedpasswords.com/range/${prefix});
const text = await res.text();
const isBreached = text.split('\n').some(line => {
const [hashSuffix, count] = line.split(':');
return hashSuffix === suffix;
});
return isBreached;
}
No API key required. No rate limit issues. And it is genuinely useful for your users.
## 4. Cloudflare Speed Test - Measure Connection Speed
Most speed test APIs require an API key or have strict rate limits. Cloudflare's endpoints do not.
Download test:
plaintext
https://speed.cloudflare.com/__down?bytes=25000000
Upload test (POST):
plaintext
https://speed.cloudflare.com/__up
You measure the time it takes to download or upload a known amount of data, then calculate Mbps:
javascript
async function testDownload() {
const bytes = 25 * 1024 * 1024;
const start = performance.now();
const res = await fetch(https://speed.cloudflare.com/__down?bytes=${bytes});
const blob = await res.blob();
const seconds = (performance.now() - start) / 1000;
return (blob.size * 8) / seconds / 1_000_000;
}
testDownload().then(mbps => {
console.log(Download speed: ${mbps.toFixed(2)} Mbps);
});
For latency, send a few small requests and take the median, not the average. One slow request should not skew the whole result.
javascript
async function testLatency() {
const samples = [];
for (let i = 0; i < 5; i++) {
const start = performance.now();
await fetch('https://speed.cloudflare.com/__down?bytes=0');
samples.push(performance.now() - start);
}
samples.sort((a, b) => a - b);
return samples[Math.floor(samples.length / 2)];
}
## 5. DNS over HTTPS - Resolve Domain Names
Google runs a public DNS resolver that speaks JSON over HTTPS:
plaintext
https://dns.google/resolve?name=example.com&type=A
It returns the same answer you would get from a DNS server, in a clean JSON format:
json
{
"Status": 0,
"Answer": [
{ "name": "example.com", "type": 1, "TTL": 300, "data": "93.184.216.34" }
]
}
You can query A, AAAA, MX, TXT, NS, CNAME, and more. No key, no limits that matter, and it works from the browser.
javascript
async function lookupDNS(domain, type = 'A') {
const url = https://dns.google/resolve?name=${domain}&type=${type};
const res = await fetch(url);
const data = await res.json();
return data.Answer || [];
}
lookupDNS('example.com', 'A').then(records => {
records.forEach(r => console.log(r.data));
});
I use this for domain lookup tools, SSL certificate checks, and verifying DNS propagation after a migration.
## 6. OpenStreetMap Tiles - Free Maps
If you have ever built a map and discovered that Google Maps charges per request, this one is for you.
OpenStreetMap provides free map tiles:
plaintext
https://tile.openstreetmap.org/{z}/{x}/{y}.png
Use them with Leaflet.js:
javascript
const map = L.map('map').setView([51.505, -0.09], 13);
L.tileLayer('https://tile.openstreetmap.org/{z}/{x}/{y}.png', {
attribution: '© OpenStreetMap contributors'
}).addTo(map);
There is a usage policy you should respect: no more than a few requests per second, and always credit OpenStreetMap. If you need higher volume, consider a commercial tile provider like MapTiler or Stadia Maps.
### One Alternative: CARTO Basemaps
If you want a cleaner look, CARTO offers free basemaps:
plaintext
https://{s}.basemaps.cartocdn.com/rastertiles/voyager/{z}/{x}/{y}{r}.png
They are faster than OpenStreetMap's default tiles in many regions and look more modern.
javascript
L.tileLayer('https://{s}.basemaps.cartocdn.com/rastertiles/voyager/{z}/{x}/{y}{r}.png', {
maxZoom: 20,
subdomains: 'abcd',
attribution: '© OpenStreetMap contributors © CARTO'
}).addTo(map);
## A Few Things to Keep in Mind
Always use HTTPS. Every API above supports it. Browsers will block mixed-content requests if you mix HTTP and HTTPS.
Always have a fallback. Public APIs go down. Wrap every fetch call in a try-catch and show a friendly message if something fails.
Never expose secrets in client-side code. None of the APIs above require a key, which is why they are safe to call from the browser. If an API requires a secret key, proxy it through your own backend.
Respect rate limits. Even free APIs have limits. Cache results where possible, and do not hammer the endpoints.
That is my list. What free APIs do you reach for most often? I am always looking for new ones to add to my toolkit.
Top comments (0)