Skip to content

Commit 06ccfa9

Browse files
oschwaldclaude
andcommitted
Add residential proxy data to anonymizer object
This adds a new residential sub-object to the anonymizer object in the GeoIP2 Insights web service response. It includes a confidence score, the provider name, and the date the network was last seen for residential proxies. The residential object may be populated even when no other anonymizer attributes are set. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
1 parent 537148d commit 06ccfa9

4 files changed

Lines changed: 85 additions & 0 deletions

File tree

CHANGELOG.md

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,13 @@
11
# Changelog
22

3+
## 1.6.0
4+
5+
* A new `residential` object has been added to the `anonymizer` object on
6+
`MaxMind::GeoIP2::Model::Insights`. This object contains residential
7+
proxy data for the network, including a confidence score, the provider
8+
name, and the date the network was last seen. This is only available
9+
from the GeoIP2 Insights web service.
10+
311
## 1.5.1 (2026-01-19)
412

513
* Re-release with a fix to the release process. This includes a bump of the

lib/maxmind/geoip2/record/anonymizer.rb

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
require 'date'
44
require 'maxmind/geoip2/record/abstract'
5+
require 'maxmind/geoip2/record/anonymizer_feed'
56

67
module MaxMind
78
module GeoIP2
@@ -11,6 +12,20 @@ module Record
1112
#
1213
# This record is returned by the Insights web service.
1314
class Anonymizer < Abstract
15+
# Residential proxy data for the network. This may be populated even
16+
# when no other anonymizer attributes are set. This property is only
17+
# available from Insights.
18+
#
19+
# @return [MaxMind::GeoIP2::Record::AnonymizerFeed]
20+
attr_reader :residential
21+
22+
# @!visibility private
23+
def initialize(record)
24+
super
25+
26+
@residential = AnonymizerFeed.new(record.nil? ? nil : record['residential'])
27+
end
28+
1429
# A score ranging from 1 to 99 that represents our percent confidence
1530
# that the network is currently part of an actively used VPN service.
1631
# This property is only available from Insights.
Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
# frozen_string_literal: true
2+
3+
require 'date'
4+
require 'maxmind/geoip2/record/abstract'
5+
6+
module MaxMind
7+
module GeoIP2
8+
module Record
9+
# Contains data for one type of anonymizer detection, currently
10+
# residential proxies. Additional feeds may be added in the future.
11+
#
12+
# This record is returned by the anonymizer object of the Insights web
13+
# service.
14+
class AnonymizerFeed < Abstract
15+
# A score ranging from 1 to 99 that represents our percent confidence
16+
# that the network is an actively used residential proxy. This
17+
# property is only available from Insights.
18+
#
19+
# @return [Integer, nil]
20+
def confidence
21+
get('confidence')
22+
end
23+
24+
# The last day that the network was sighted in our analysis of
25+
# residential proxies. This value is parsed lazily. This property is
26+
# only available from Insights.
27+
#
28+
# @return [Date, nil] A Date object representing the last seen date,
29+
# or nil if the date is not available.
30+
def network_last_seen
31+
return @network_last_seen if defined?(@network_last_seen)
32+
33+
date_string = get('network_last_seen')
34+
35+
if !date_string
36+
return nil
37+
end
38+
39+
@network_last_seen = Date.parse(date_string)
40+
end
41+
42+
# The name of the residential proxy provider associated with the
43+
# network. This property is only available from Insights.
44+
#
45+
# @return [String, nil]
46+
def provider_name
47+
get('provider_name')
48+
end
49+
end
50+
end
51+
end
52+
end

test/test_client.rb

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,11 @@ class ClientTest < Minitest::Test
3838
'is_tor_exit_node' => false,
3939
'network_last_seen' => '2025-10-15',
4040
'provider_name' => 'nordvpn',
41+
'residential' => {
42+
'confidence' => 82,
43+
'network_last_seen' => '2026-05-11',
44+
'provider_name' => 'quickshift',
45+
},
4146
},
4247
'continent' => {
4348
'code' => 'NA',
@@ -109,6 +114,11 @@ def test_insights
109114
assert_equal(Date.parse('2025-10-15'), record.anonymizer.network_last_seen)
110115
assert_equal('nordvpn', record.anonymizer.provider_name)
111116

117+
# Test anonymizer.residential object
118+
assert_equal(82, record.anonymizer.residential.confidence)
119+
assert_equal(Date.parse('2026-05-11'), record.anonymizer.residential.network_last_seen)
120+
assert_equal('quickshift', record.anonymizer.residential.provider_name)
121+
112122
# Test traits
113123
assert(record.traits.anycast?)
114124
assert(record.traits.residential_proxy?)

0 commit comments

Comments
 (0)