SDKs
Markdown

PHP SDK

Official IPScope server-side client for PHP 8.2+ (PHP-FPM, FrankenPHP, RoadRunner & Swoole) (ipscope/ipscope-php).

# Install

Install
composer require ipscope/ipscope-php

# Quickstart: single, batch & prefix lookups

Pass your API key explicitly or set IPSCOPE_KEY in your environment. Every lookup returns the canonical response schema with geo, network, connection, security and security_extensions.

PHP
<?php

declare(strict_types=1);

use IpScope\Sdk\IpScopeClient;
use IpScope\Sdk\IpScopeSecurity;

// Optional: inspect runtime patch status for CVE-2026-109618 / CVE-2026-109619
$advisory = IpScopeSecurity::getRuntimeAdvisoryStatus();

$client = new IpScopeClient(apiKey: getenv('IPSCOPE_KEY') ?: '');

// 1. Single IPv4 or IPv6 lookup (cached automatically in bounded LRU cache)
$ipInfo = $client->lookupIp('198.51.100.7');
echo $ipInfo->ip . ' ' . $ipInfo->geo->countryCode . ' AS' . $ipInfo->network->asn . PHP_EOL;
echo 'VPN: ' . ($ipInfo->security->isVpn ? 'true' : 'false') . PHP_EOL;

// 2. Batch lookup (up to 100 IPs; deduplicates & reuses cached entries)
$batch = $client->lookupBatch(['198.51.100.7', '1.1.1.1', '2606:4700:4700::1111']);
foreach ($batch->results as $record) {
    echo $record->ip . ' -> ' . $record->network->org . PHP_EOL;
}

// 3. Memory-bounded generator streaming for 10,000+ IPs (constant O(chunk) RAM)
foreach ($client->lookupBatchStream($largeIpList) as $chunk) {
    foreach ($chunk->results as $record) {
        // Process each record with < 400 KB steady-state memory overhead
    }
}

// 4. Network CIDR prefix lookup
$prefix = $client->lookupNetwork('198.51.100.0/24');
echo $prefix->queriedCidr . ' -> AS' . $prefix->record?->asn . ' (' . $prefix->record?->organization . ')' . PHP_EOL;
Responses
application/json

1. Single IPv4/IPv6 lookup response (GET /v1/ip/{ip})

{
  "ip": "198.51.100.7",
  "ip_version": 4,
  "matched_network": "198.51.100.0/24",
  "geo": {
    "country_code": "US",
    "declared_country_code": "US",
    "physical_country_code": "US",
    "is_virtual_location": false,
    "location_type": "physical",
    "confidence": 0.94,
    "subdivision": "Virginia",
    "city": "Ashburn",
    "postal_code": "20147",
    "latitude": 39.0438,
    "longitude": -77.4874,
    "accuracy_radius_km": 10,
    "timezone": "America/New_York"
  },
  "network": {
    "asn": 64501,
    "organization": "Example Cloud LLC"
  },
  "connection": {
    "connection_type": "hosting",
    "is_hosting": true,
    "is_residential": false,
    "is_mobile": false,
    "is_business": false
  },
  "security": {
    "is_vpn": true,
    "is_hosting": true,
    "is_tor_exit": false,
    "is_proxy": false,
    "anonymizer_type": "vpn",
    "confidence": 0.96,
    "reason_codes": [
      "vpn_handshake_confirmed",
      "datacenter_asn_range"
    ]
  },
  "security_extensions": {
    "abuse_velocity_score": 18,
    "is_known_scanner": false,
    "observation_recency_hours": 12,
    "anonymizer_reason": "vpn_handshake_confirmed",
    "threat_level": "medium",
    "abuse_velocity": "low",
    "confidence": 0.96
  },
  "dataset_version": "2026-10-27T00:00:00Z.crawl-1793088000000",
  "updated_at": "2026-10-27T00:00:00Z"
}
application/json

4. Network CIDR prefix lookup response (GET /v1/networks/{prefix}/{length})

{
  "queried_cidr": "198.51.100.0/24",
  "family": 4,
  "dataset_version": "2026-10-27T00:00:00Z.crawl-1793088000000",
  "record": {
    "prefix": "198.51.100.0/24",
    "family": 4,
    "asn": 64501,
    "organization": "Example Cloud LLC",
    "countryCode": "US",
    "city": "Ashburn",
    "locationType": "physical",
    "isVpn": true,
    "isHosting": true,
    "isTorExit": false,
    "isProxy": false,
    "anonymizerType": "vpn"
  }
}

# Architecture & runtime guarantees

  • Hardened against PHP Zend Engine OOM & persistent-worker vulnerabilities (CVE-2026-109618 & CVE-2026-109619) via pre-OOM heap headroom guards (IpScopeSecurity::assertMemoryHeadroom).
  • Streaming CURLOPT_WRITEFUNCTION inspection aborts oversized responses before buffering, with bounded JSON recursion (max_depth = 16).
  • Zero static or global state across persistent worker requests (FrankenPHP, RoadRunner, Swoole, PHP-FPM).

# Reading local MMDB files

If you subscribe to a downloadable database, our .mmdb snapshots open directly in standard MaxMind DB readers with sub-microsecond in-memory lookups:

PHP (MMDB)
<?php
use MaxMind\Db\Reader;

$reader = new Reader('/var/lib/ipscope/ipscope-complete.mmdb');
$record = $reader->get('198.51.100.7');
$reader->close();

# Plain HTTP fallback

Need to call the REST API without installing a package? Use PHP’s standard HTTP client directly:

PHP (HTTP)
<?php
$ch = curl_init('https://api.ipscope.io/v1/ip/198.51.100.7');
curl_setopt_array($ch, [
    CURLOPT_HTTPHEADER => ['Authorization: Bearer ' . getenv('IPSCOPE_KEY')],
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_TIMEOUT => 5,
]);
$info = json_decode((string) curl_exec($ch), true, 16, JSON_THROW_ON_ERROR);