PHPackages                             ipwhois/ipwhois-php - PHPackages - PHPackages  [Skip to content](#main-content)[PHPackages](/)[Directory](/)[Categories](/categories)[Trending](/trending)[Leaderboard](/leaderboard)[Changelog](/changelog)[Analyze](/analyze)[Collections](/collections)[Log in](/login)[Sign up](/register)

1. [Directory](/)
2. /
3. [API Development](/categories/api)
4. /
5. ipwhois/ipwhois-php

ActiveLibrary[API Development](/categories/api)

ipwhois/ipwhois-php
===================

Official PHP client for the ipwhois.io IP Geolocation API. Simple, dependency-free, supports single and bulk IP lookups.

v1.2.1(4w ago)855↓100%4MITPHPPHP ^8.0

Since May 8Pushed 4w ago7 watchersCompare

[ Source](https://github.com/IPWhois/ipwhois-php)[ Packagist](https://packagist.org/packages/ipwhois/ipwhois-php)[ Docs](https://ipwhois.io)[ RSS](/packages/ipwhois-ipwhois-php/feed)WikiDiscussions main Synced 1w ago

READMEChangelogDependencies (1)Versions (10)Used By (0)

ipwhois-php
===========

[](#ipwhois-php)

[![Packagist Version](https://camo.githubusercontent.com/4f1aab084212e70d48aaae16c277547fbb652f73a10279bc070eaa2dacac706d/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f762f697077686f69732f697077686f69732d7068702e737667)](https://packagist.org/packages/ipwhois/ipwhois-php)[![PHP Version](https://camo.githubusercontent.com/26157cf2cb5ef3dfd562c32804e22fedb16ba353742b57e02bdbaffe4ddf5036/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f7068702d762f697077686f69732f697077686f69732d7068702e737667)](https://packagist.org/packages/ipwhois/ipwhois-php)[![License](https://camo.githubusercontent.com/7013272bd27ece47364536a221edb554cd69683b68a46fc0ee96881174c4214c/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f6c6963656e73652d4d49542d626c75652e737667)](LICENSE)

Official, dependency-free PHP client for the [ipwhois.io](https://ipwhois.io) IP Geolocation API.

- ✅ Single and bulk IP lookups (IPv4 and IPv6)
- ✅ Works with both the **Free** and **Paid** plans
- ✅ HTTPS by default
- ✅ Localisation, field selection, threat detection, rate info
- ✅ Never throws — all errors returned as `success: false` arrays
- ✅ No external dependencies — only the cURL extension
- ✅ PHP 8.0+

Installation
------------

[](#installation)

```
composer require ipwhois/ipwhois-php
```

Free vs Paid plan
-----------------

[](#free-vs-paid-plan)

The same `IPWhois` class is used for both plans. The only difference is whether you pass an API key:

- **Free plan** — create the client **without arguments**. No API key, no signup required. Suitable for low-traffic and non-commercial use.
- **Paid plan** — create the client **with your API key** from . Higher limits, plus access to bulk lookups and threat-detection data.

```
$free = new \Ipwhois\IPWhois();               // Free plan — no API key
$paid = new \Ipwhois\IPWhois('YOUR_API_KEY'); // Paid plan — with API key
```

Everything else (`lookup()`, options, error handling) is identical.

Quick start — Free plan (no API key)
------------------------------------

[](#quick-start--free-plan-no-api-key)

```
require 'vendor/autoload.php';

use Ipwhois\IPWhois;

$ipwhois = new IPWhois(); // no API key

$info = $ipwhois->lookup('8.8.8.8');

echo $info['country'] . ' ' . $info['flag']['emoji'] . PHP_EOL;
// → United States 🇺🇸

echo $info['city'] . ', ' . $info['region'] . PHP_EOL;
// → Mountain View, California
```

Quick start — Paid plan (with API key)
--------------------------------------

[](#quick-start--paid-plan-with-api-key)

Get an API key at  and pass it to the constructor:

```
require 'vendor/autoload.php';

use Ipwhois\IPWhois;

$ipwhois = new IPWhois('YOUR_API_KEY'); // with API key

$info = $ipwhois->lookup('8.8.8.8');

echo $info['country'] . ' ' . $info['flag']['emoji'] . PHP_EOL;
// → United States 🇺🇸

echo $info['city'] . ', ' . $info['region'] . PHP_EOL;
// → Mountain View, California
```

> ℹ️ Pass nothing to look up your own public IP: `$ipwhois->lookup();` — works on both plans.

Lookup options
--------------

[](#lookup-options)

Every option below can be passed per call, or set once on the client as a default.

OptionTypePlans neededDescription`lang`stringFree + PaidOne of: `en`, `ru`, `de`, `es`, `pt-BR`, `fr`, `zh-CN`, `ja``fields`arrayFree + PaidRestrict the response to specific fields (e.g. `['country', 'city']`)`rate`boolBasic and aboveInclude the `rate` block (`limit`, `remaining`)`security`boolBusiness and aboveInclude the `security` block (proxy/vpn/tor/hosting)### Setting defaults once

[](#setting-defaults-once)

Every option can be passed two ways: **per call** (as the second argument to `lookup()` / `bulkLookup()`) or **once as a default** on the client. Per-call options always override the defaults, so it's safe to set sensible defaults and only override what differs for a specific call.

Defaults are set with fluent setters — `setLanguage()`, `setFields()`, `setSecurity()`, `setRate()`, `setTimeout()`, `setConnectTimeout()`, `setUserAgent()` — and can be chained:

```
use Ipwhois\IPWhois;

// Free plan
$ipwhois = (new IPWhois())
    ->setLanguage('en')
    ->setFields(['success', 'country', 'city', 'flag.emoji'])
    ->setTimeout(8);
```

```
use Ipwhois\IPWhois;

// Paid plan
$ipwhois = (new IPWhois('YOUR_API_KEY'))
    ->setLanguage('en')
    ->setFields(['success', 'country', 'city', 'flag.emoji'])
    ->setTimeout(8);
```

Either client behaves the same way at call time — per-call options always win over the defaults:

```
$ipwhois->lookup('8.8.8.8');                   // uses lang=en, the field whitelist, and timeout=8
$ipwhois->lookup('1.1.1.1', ['lang' => 'de']); // overrides lang for this single call only
```

> ⚠️ When you restrict fields with `setFields()` (or the per-call `'fields'`option), the API only returns the fields you ask for. Always include `'success'` in the list if you rely on `$info['success']` for error checking — otherwise the field will be missing on responses.

> ℹ️ `setSecurity(true)` requires Business+ and `setRate(true)` requires Basic+. See the table above for what's available where.

HTTPS Encryption
----------------

[](#https-encryption)

By default, all requests are sent over HTTPS. If you need to disable it (for example, in environments without an up-to-date CA bundle), pass `'ssl' => false`to the constructor:

```
use Ipwhois\IPWhois;

// Free plan
$ipwhois = new IPWhois(null, ['ssl' => false]);
```

```
use Ipwhois\IPWhois;

// Paid plan
$ipwhois = new IPWhois('YOUR_API_KEY', ['ssl' => false]);
```

> ℹ️ HTTPS is strongly recommended for production traffic — your API key is sent in the query string and would otherwise travel in clear text.

Bulk lookup (Paid plan only)
----------------------------

[](#bulk-lookup-paid-plan-only)

The bulk endpoint sends **up to 100 IPs** in a single GET request. Each address counts as one credit. Available on the **Business** and **Unlimited**plans.

```
$ipwhois = new IPWhois('YOUR_API_KEY');

$results = $ipwhois->bulkLookup([
    '8.8.8.8',
    '1.1.1.1',
    '208.67.222.222',
    '2c0f:fb50:4003::',   // IPv6 is fine — mix freely
]);

foreach ($results as $row) {
    if (($row['success'] ?? false) === false) {
        // Per-IP errors (e.g. "Invalid IP address") are returned inline,
        // they do NOT throw — the rest of the batch is still usable.
        echo "skip {$row['ip']}: {$row['message']}\n";
        continue;
    }
    echo "{$row['ip']} → {$row['country']}\n";
}
```

> ℹ️ Bulk requires an API key. Calling `bulkLookup()` without one will fail at the API level.

Error handling
--------------

[](#error-handling)

**The library never throws.** Every failure — invalid IP, bad API key, rate limit, network outage, missing extension, bad options — comes back inside the response array with `success => false` and a `message`. Just check `$info['success']` after every call:

```
$info = $ipwhois->lookup('8.8.8.8');

if (!$info['success']) {
    error_log("Lookup failed: {$info['message']}");
    return;
}

echo $info['country'];
```

This means an outage of the ipwhois.io API (or of your server's DNS, connection, etc.) will never surface as a fatal error in your application — you decide how to react.

### Error response fields

[](#error-response-fields)

Every error response contains `success: false`, a human-readable `message`, and an `error_type` so you can branch on the category of the failure. Some errors include extra fields you can branch on:

FieldWhen it's present`success`Always — false for error responses (true for successful responses)`message`Always — human-readable description of what went wrong`error_type`Always — one of `'api'`, `'network'`, `'environment'`, or `'invalid_argument'``http_status`On HTTP 4xx / 5xx responses`retry_after`On HTTP 429 — **free plan only** (the paid endpoint does not send a `Retry-After` header)```
$info = $ipwhois->lookup('8.8.8.8');

if (!$info['success']) {
    if (($info['http_status'] ?? 0) === 429) {
        sleep($info['retry_after'] ?? 60);
        // …retry
    }
    if (($info['error_type'] ?? null) === 'network') {
        // DNS failure, connection refused, timeout, …
    }
    error_log("Error: {$info['message']}");
    return;
}
```

Response shape
--------------

[](#response-shape)

A successful response includes (depending on your plan and selected options):

```
{
    "ip": "8.8.4.4",
    "success": true,
    "type": "IPv4",
    "continent": "North America",
    "continent_code": "NA",
    "country": "United States",
    "country_code": "US",
    "region": "California",
    "region_code": "CA",
    "city": "Mountain View",
    "latitude": 37.3860517,
    "longitude": -122.0838511,
    "is_eu": false,
    "postal": "94039",
    "calling_code": "1",
    "capital": "Washington D.C.",
    "borders": "CA,MX",
    "flag": {
        "img": "https://cdn.ipwhois.io/flags/us.svg",
        "emoji": "🇺🇸",
        "emoji_unicode": "U+1F1FA U+1F1F8"
    },
    "connection": {
        "asn": 15169,
        "org": "Google LLC",
        "isp": "Google LLC",
        "domain": "google.com"
    },
    "timezone": {
        "id": "America/Los_Angeles",
        "abbr": "PDT",
        "is_dst": true,
        "offset": -25200,
        "utc": "-07:00",
        "current_time": "2026-05-08T14:31:48-07:00"
    },
    "currency": {
        "name": "US Dollar",
        "code": "USD",
        "symbol": "$",
        "plural": "US dollars",
        "exchange_rate": 1
    },
    "security": {
        "anonymous": false,
        "proxy": false,
        "vpn": false,
        "tor": false,
        "hosting": false
    },
    "rate": {
        "limit": 250000,
        "remaining": 50155
    }
}
```

For the full field reference, see the [official documentation](https://ipwhois.io/documentation).

An **error** response looks like:

```
{
    "success": false,
    "message": "Rate limit exceeded",
    "error_type": "api",       // 'api' / 'network' / 'environment' / 'invalid_argument'
    "http_status": 429,         // present for HTTP 4xx / 5xx
    "retry_after": 60       // additionally present on HTTP 429 — free plan only
}
```

Requirements
------------

[](#requirements)

- PHP **8.0** or newer
- ext-curl
- ext-json

Contributing
------------

[](#contributing)

Issues and pull requests are welcome on [GitHub](https://github.com/IPWhois/ipwhois-php).

License
-------

[](#license)

[MIT](LICENSE) © ipwhois.io

###  Health Score

45

—

FairBetter than 91% of packages

Maintenance94

Actively maintained with recent releases

Popularity20

Limited adoption so far

Community12

Small or concentrated contributor base

Maturity44

Maturing project, gaining track record

 Bus Factor1

Top contributor holds 100% of commits — single point of failure

How is this calculated?**Maintenance (25%)** — Last commit recency, latest release date, and issue-to-star ratio. Uses a 2-year decay window.

**Popularity (30%)** — Total and monthly downloads, GitHub stars, and forks. Logarithmic scaling prevents top-heavy scores.

**Community (15%)** — Contributors, dependents, forks, watchers, and maintainers. Measures real ecosystem engagement.

**Maturity (30%)** — Project age, version count, PHP version support, and release stability.

###  Release Activity

Cadence

Every ~0 days

Total

9

Last Release

29d ago

### Community

Maintainers

![](https://www.gravatar.com/avatar/96a3c4e706f72536151484146f9a698f159c7109db976102db93909ff880c837?d=identicon)[ipwhois](/maintainers/ipwhois)

---

Top Contributors

[![ipwhois-io](https://avatars.githubusercontent.com/u/47532184?v=4)](https://github.com/ipwhois-io "ipwhois-io (18 commits)")

---

Tags

geoipip-apiip-geolocationip-geolocation-apiip-locationip-location-apiip-lookupip-lookup-apiipwhoisphpgeoipgeolocationIP APIip geolocationip-lookupipwhoisip-locator

###  Code Quality

TestsPHPUnit

### Embed Badge

![Health badge](/badges/ipwhois-ipwhois-php/health.svg)

```
[![Health](https://phpackages.com/badges/ipwhois-ipwhois-php/health.svg)](https://phpackages.com/packages/ipwhois-ipwhois-php)
```

###  Alternatives

[geoip2/geoip2

MaxMind GeoIP PHP API

2.5k89.6M339](/packages/geoip2-geoip2)[torann/geoip

Support for multiple Geographical Location services.

2.3k14.9M92](/packages/torann-geoip)[ipgeolocation/ipgeolocation-php-sdk

Official PHP SDK for the IPGeolocation.io IP Location API with single and bulk lookup support.

413.2k](/packages/ipgeolocation-ipgeolocation-php-sdk)[pulkitjalan/ip-geolocation

IP Geolocation Wrapper with Laravel Support

91194.7k1](/packages/pulkitjalan-ip-geolocation)[interaction-design-foundation/laravel-geoip

Support for multiple Geographical Location services.

19253.0k3](/packages/interaction-design-foundation-laravel-geoip)[atchondjo/geoip2country

A lightweight but powerful IP address lookup database solution to determine visitors country

344.5k](/packages/atchondjo-geoip2country)

PHPackages © 2026

[Directory](/)[Categories](/categories)[Trending](/trending)[Changelog](/changelog)[Analyze](/analyze)
