# Official Server SDKs

> Eight production-ready server-side client libraries for Python, Node.js, Go, Rust, Java, .NET, Ruby and PHP.

Every official IPScope SDK wraps the [REST API](https://ipscope.io/docs/api-reference) with zero-bloat transport, bounded O(1) in-memory LRU caching, automatic batch deduplication, memory-bounded streaming for 10,000+ IP lists, and exponential backoff with jitter on `429` and `5xx` responses.

| Language | Package | Runtime | Install | Status |
| --- | --- | --- | --- | --- |
| [Python](https://ipscope.io/docs/sdks/python) | `ipscope` | Python 3.10+ (asyncio & sync) | `pip install ipscope` | Stable |
| [Node.js](https://ipscope.io/docs/sdks/node) | `@ipscope/sdk-node` | Node.js 18+, Bun, Deno & Edge Workers | `npm install @ipscope/sdk-node` | Stable |
| [Go](https://ipscope.io/docs/sdks/go) | `github.com/ipscope-io/ipscope-go` | Go 1.22+ | `go get github.com/ipscope-io/ipscope-go` | Stable |
| [Rust](https://ipscope.io/docs/sdks/rust) | `ipscope` | Rust 1.75+ (2021 edition, Tokio async & blocking) | `cargo add ipscope` | Stable |
| [Java](https://ipscope.io/docs/sdks/java) | `io.ipscope:ipscope-sdk` | Java 17+ (Java 21 Virtual Threads ready) | `io.ipscope:ipscope-sdk:1.0.0` | Stable |
| [.NET](https://ipscope.io/docs/sdks/dotnet) | `IpScope.Sdk` | .NET 8.0+ (C# 12) | `dotnet add package IpScope.Sdk` | Stable |
| [Ruby](https://ipscope.io/docs/sdks/ruby) | `ipscope` | Ruby 3.1+ (Puma, Sidekiq & Falcon Fiber-safe) | `gem install ipscope` | Stable |
| [PHP](https://ipscope.io/docs/sdks/php) | `ipscope/ipscope-php` | PHP 8.2+ (PHP-FPM, FrankenPHP, RoadRunner & Swoole) | `composer require ipscope/ipscope-php` | Stable |

## Compare a single lookup across languages

```bash curl
curl -sS "https://api.ipscope.io/v1/ip/198.51.100.7" \
  -H "Authorization: Bearer $IPSCOPE_KEY"
```

```python Python
import asyncio, os
from ipscope import AsyncIpScopeClient

async def main() -> None:
    async with AsyncIpScopeClient(api_key=os.environ["IPSCOPE_KEY"]) as client:
        record = await client.lookup_ip("198.51.100.7")
        print(record["ip"], record["geo"]["country_code"], record["security"]["is_vpn"])

asyncio.run(main())
```

```ts Node.js
import { IpScopeClient } from '@ipscope/sdk-node';

const client = new IpScopeClient({ apiKey: process.env.IPSCOPE_KEY });
const record = await client.lookupIp('198.51.100.7');
console.log(record.ip, record.geo?.country_code, record.security?.is_vpn);
```

```go Go
client := ipscope.NewClient(ipscope.Config{APIKey: os.Getenv("IPSCOPE_KEY")})
defer client.Close()

record, err := client.LookupIP(ctx, "198.51.100.7")
if err != nil {
	return err
}
fmt.Println(record.IP, record.Security.IsVPN)
```

```rust Rust
use ipscope::{AsyncIpScopeClient, ClientConfig};

let client = AsyncIpScopeClient::new(ClientConfig::new(std::env::var("IPSCOPE_KEY")?))?;
let record = client.lookup_ip("198.51.100.7").await?;
println!("{} VPN={}", record.ip, record.security.is_vpn);
```

```java Java
import io.ipscope.sdk.IpScopeClient;
import io.ipscope.sdk.IpScopeConfig;

IpScopeConfig config = IpScopeConfig.builder().apiKey(System.getenv("IPSCOPE_KEY")).build();
try (IpScopeClient client = new IpScopeClient(config)) {
    var record = client.lookupIp("198.51.100.7");
    System.out.println(record.ip() + " " + record.geo().countryCode());
}
```

```csharp .NET
using IpScope.Sdk;

using var client = new IpScopeClient(new IpScopeClientOptions {
    ApiKey = Environment.GetEnvironmentVariable("IPSCOPE_KEY")
});
var record = await client.LookupIpAsync("198.51.100.7");
Console.WriteLine($"{record.Ip} {record.Geo?.CountryCode} VPN={record.Security?.IsVpn}");
```

```ruby Ruby
require "ipscope"

client = IpScope::Client.new(api_key: ENV.fetch("IPSCOPE_KEY"))
record = client.lookup_ip("198.51.100.7")
puts "#{record.ip} #{record.geo.country_code} VPN=#{record.security.is_vpn}"
```

```php PHP
<?php
use IpScope\Sdk\IpScopeClient;

$client = new IpScopeClient(apiKey: getenv('IPSCOPE_KEY') ?: '');
$record = $client->lookupIp('198.51.100.7');
echo $record->ip . " " . $record->geo->countryCode . PHP_EOL;
```

## What every official SDK guarantees

- **Scoped strictly to IP intelligence**: single IP (`/v1/ip/{ip}`), caller IP (`/v1/ip/me`), batch (`/v1/ip/batch`), network CIDR (`/v1/network/{cidr}`), dataset catalog (`/v1/datasets`), and geolocation feedback (`/v1/feedback`).
- **Bounded O(1) LRU cache**: hot IP addresses are served from memory (`2,048` entries by default) and automatically reused across `lookupBatch` calls so duplicate IPs in a batch never consume quota twice.
- **Constant-memory batch streaming**: `lookup_batch_stream` / `lookupBatchStream` chunks arbitrarily large iterables into 100-IP requests with constant `< 400 KB` heap overhead.
- **Resilient retry policy**: honours `Retry-After` headers on `429` and retries transient `502`/`503`/`504` errors with exponential backoff + jitter.

For air-gapped or local zero-latency lookups, our `.mmdb` files open directly in standard MaxMind readers in every language. See [Reading MMDB](https://ipscope.io/docs/databases/reading-mmdb).

- [Python SDK](https://ipscope.io/docs/sdks/python) (Stable): Python 3.10+ (asyncio & sync) · `pip install ipscope`
- [Node.js SDK](https://ipscope.io/docs/sdks/node) (Stable): Node.js 18+, Bun, Deno & Edge Workers · `npm install @ipscope/sdk-node`
- [Go SDK](https://ipscope.io/docs/sdks/go) (Stable): Go 1.22+ · `go get github.com/ipscope-io/ipscope-go`
- [Rust SDK](https://ipscope.io/docs/sdks/rust) (Stable): Rust 1.75+ (2021 edition, Tokio async & blocking) · `cargo add ipscope`
- [Java SDK](https://ipscope.io/docs/sdks/java) (Stable): Java 17+ (Java 21 Virtual Threads ready) · `io.ipscope:ipscope-sdk:1.0.0`
- [.NET SDK](https://ipscope.io/docs/sdks/dotnet) (Stable): .NET 8.0+ (C# 12) · `dotnet add package IpScope.Sdk`
- [Ruby SDK](https://ipscope.io/docs/sdks/ruby) (Stable): Ruby 3.1+ (Puma, Sidekiq & Falcon Fiber-safe) · `gem install ipscope`
- [PHP SDK](https://ipscope.io/docs/sdks/php) (Stable): PHP 8.2+ (PHP-FPM, FrankenPHP, RoadRunner & Swoole) · `composer require ipscope/ipscope-php`
