From a08f8514e3028ad108e5edc6f81cf391b19b5ae7 Mon Sep 17 00:00:00 2001 From: Gregory Oschwald Date: Fri, 10 Jul 2026 20:52:40 +0000 Subject: [PATCH] Add residential proxy data to anonymizer object This adds support for the new residential sub-object nested within the anonymizer object in the GeoIP2 Insights web service response. The residential object contains a confidence score, the last seen date for the network, and the associated provider name. The residential property may be populated even when no other anonymizer properties are set. The shared shape of these feed records is exposed as a new AnonymizerFeedRecord interface so it can be reused if additional feeds are added in the future. Co-Authored-By: Claude Fable 5 --- CHANGELOG.md | 16 ++++++++++++++++ fixtures/geoip2.json | 7 ++++++- src/records.ts | 32 ++++++++++++++++++++++++++++++++ src/webServiceClient.spec.ts | 8 +++++++- 4 files changed, 61 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 7c909810..d1cf826a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,22 @@ CHANGELOG ========= +7.1.0 (unreleased) +------------------ + +* A new `residential` property has been added to the `anonymizer` object in + the `Insights` response model. This contains residential proxy data for + the network and is available from the GeoIP2 Insights web service only. + The `residential` property may be populated even when no other + `anonymizer` properties are set. The `residential` object includes the + following properties: + * `confidence`: A score (1-99) representing MaxMind's confidence that the + network is an actively used residential proxy + * `networkLastSeen`: The last day (YYYY-MM-DD) the network was sighted in + our analysis of residential proxies + * `providerName`: The name of the residential proxy provider associated + with the network + 7.0.0 (2026-06-29) ------------------ diff --git a/fixtures/geoip2.json b/fixtures/geoip2.json index 216e9e7f..f51ed6a0 100644 --- a/fixtures/geoip2.json +++ b/fixtures/geoip2.json @@ -139,6 +139,11 @@ "is_residential_proxy": false, "is_tor_exit_node": false, "network_last_seen": "2025-04-14", - "provider_name": "NordVPN" + "provider_name": "NordVPN", + "residential": { + "confidence": 82, + "network_last_seen": "2026-05-11", + "provider_name": "quickshift" + } } } diff --git a/src/records.ts b/src/records.ts index 8cfdeadb..7886b4a0 100644 --- a/src/records.ts +++ b/src/records.ts @@ -217,6 +217,32 @@ export interface SubdivisionsRecord { readonly names: Names; } +/** + * Contains data for one type of anonymizer detection, currently residential + * proxies. These records are nested within the anonymizer record, such as + * `residential`, and additional feeds may be added in the future. This + * record is only available from the GeoIP Insights web service. + */ +export interface AnonymizerFeedRecord { + /** + * A score ranging from 1 to 99 that represents our percent confidence that + * the network is currently part of this anonymizer feed. This value is + * only available from GeoIP Insights. + */ + readonly confidence?: number; + /** + * The last day that the network was sighted in our analysis of this + * anonymizer feed. The date is in ISO 8601 format (YYYY-MM-DD). This value + * is only available from GeoIP Insights. + */ + readonly networkLastSeen?: string; + /** + * The name of the provider associated with the network in this anonymizer + * feed. This value is only available from GeoIP Insights. + */ + readonly providerName?: string; +} + /** * Contains data for the anonymizer record associated with an IP address. * This record is only available from the GeoIP Insights web service. @@ -271,6 +297,12 @@ export interface AnonymizerRecord { * This value is only available from GeoIP Insights. */ readonly providerName?: string; + /** + * Residential proxy data for the network. This may be populated even when + * no other anonymizer properties are set. This value is only available + * from GeoIP Insights. + */ + readonly residential?: AnonymizerFeedRecord; } /** diff --git a/src/webServiceClient.spec.ts b/src/webServiceClient.spec.ts index 402a06e8..93c866c5 100644 --- a/src/webServiceClient.spec.ts +++ b/src/webServiceClient.spec.ts @@ -346,7 +346,7 @@ describe('WebServiceClient', () => { it('returns an insight class', async () => { const ip = '8.8.8.8'; - expect.assertions(107); + expect.assertions(110); const { client, requests } = clientWith(() => jsonResponse(200, testFixture) @@ -474,6 +474,12 @@ describe('WebServiceClient', () => { expect(got.anonymizer!.isTorExitNode).toEqual(false); expect(got.anonymizer!.networkLastSeen).toEqual('2025-04-14'); expect(got.anonymizer!.providerName).toEqual('NordVPN'); + + expect(got.anonymizer!.residential!.confidence).toEqual(82); + expect(got.anonymizer!.residential!.networkLastSeen).toEqual( + '2026-05-11' + ); + expect(got.anonymizer!.residential!.providerName).toEqual('quickshift'); }); });