<?xml version="1.0" encoding="UTF-8"?><rss version="2.0" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:ajvb="https://ajvanbeest.com/ns/feed"><channel><title>AJ Van Beest — Playbooks</title><description>Playbooks from ajvanbeest.com. I build robots to fight cybercrime. Writing, projects, notes and playbooks on security automation and agentic systems; every page is also available as markdown (.md) and JSON (.json).</description><link>https://ajvanbeest.com/</link><language>en-us</language><atom:link href="https://ajvanbeest.com/playbooks/rss.xml" rel="self" type="application/rss+xml"/><item><title>Playbook: Find the Geolocation of an External IP Address</title><link>https://ajvanbeest.com/playbooks/geoip-lookup/</link><guid isPermaLink="true">https://ajvanbeest.com/playbooks/geoip-lookup/</guid><description>Determine the geographic location of an external IP address using multiple sources, and validate that the results are consistent.</description><pubDate>Thu, 01 Jan 2026 00:00:00 GMT</pubDate><content:encoded>&lt;h2 id=&quot;purpose&quot;&gt;Purpose&lt;/h2&gt;
&lt;p&gt;Determine the geographic location of an external IP address using multiple sources, and validate that the results are consistent.&lt;/p&gt;
&lt;h2 id=&quot;required-tools--access&quot;&gt;Required Tools &amp;amp; Access&lt;/h2&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Tool&lt;/th&gt;
&lt;th&gt;Access Needed&lt;/th&gt;
&lt;th&gt;Free Tier?&lt;/th&gt;
&lt;th&gt;Notes&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;a href=&quot;https://ipinfo.io&quot;&gt;IPinfo.io&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;API token or web interface&lt;/td&gt;
&lt;td&gt;Yes (50k/month)&lt;/td&gt;
&lt;td&gt;Privacy detection requires paid plan&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;a href=&quot;http://ip-api.com&quot;&gt;ip-api.com&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;No auth for non-commercial&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;td&gt;Includes proxy/hosting flags&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;a href=&quot;https://virustotal.com&quot;&gt;VirusTotal&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;API key or web interface&lt;/td&gt;
&lt;td&gt;Yes (limited)&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;a href=&quot;https://abuseipdb.com&quot;&gt;AbuseIPDB&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;API key or web interface&lt;/td&gt;
&lt;td&gt;Yes (1k/day)&lt;/td&gt;
&lt;td&gt;Tor/proxy detection&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;a href=&quot;https://check.torproject.org/torbulkexitlist&quot;&gt;Tor Exit Node List&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;None&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;td&gt;Official Tor Project list&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;You need at least two geolocation sources to cross-validate results.&lt;/p&gt;
&lt;h2 id=&quot;input&quot;&gt;Input&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;One external IPv4 or IPv6 address (e.g., &lt;code&gt;8.8.8.8&lt;/code&gt;)&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;steps&quot;&gt;Steps&lt;/h2&gt;
&lt;h3 id=&quot;1-query-ipinfoio&quot;&gt;1. Query IPinfo.io&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;Web interface:&lt;/strong&gt;&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Go to &lt;a href=&quot;https://ipinfo.io&quot;&gt;https://ipinfo.io&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Enter the IP address in the search box&lt;/li&gt;
&lt;li&gt;Record: City, Region, Country, Organization, ASN&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;strong&gt;API:&lt;/strong&gt;&lt;/p&gt;
&lt;pre class=&quot;astro-code astro-code-themes gruvbox-light-medium gruvbox-dark-medium&quot; style=&quot;--shiki-light:#3c3836;--shiki-dark:#ebdbb2;--shiki-light-bg:#fbf1c7;--shiki-dark-bg:#282828; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;bash&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;--shiki-light:#B57614;--shiki-dark:#FABD2F&quot;&gt;curl&lt;/span&gt;&lt;span style=&quot;--shiki-light:#7C6F64;--shiki-dark:#A89984&quot;&gt; &quot;&lt;/span&gt;&lt;span style=&quot;--shiki-light:#79740E;--shiki-dark:#B8BB26&quot;&gt;https://ipinfo.io/{IP_ADDRESS}?token={YOUR_TOKEN}&lt;/span&gt;&lt;span style=&quot;--shiki-light:#7C6F64;--shiki-dark:#A89984&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Record the following fields:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;city&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;region&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;country&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;org&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;asn&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;2-query-ip-apicom&quot;&gt;2. Query ip-api.com&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;Web interface:&lt;/strong&gt;&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Go to &lt;a href=&quot;http://ip-api.com&quot;&gt;http://ip-api.com&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;The IP appears in the URL; modify to: &lt;code&gt;http://ip-api.com/json/{IP_ADDRESS}&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Record: City, Region, Country, ISP, AS&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;strong&gt;API:&lt;/strong&gt;&lt;/p&gt;
&lt;pre class=&quot;astro-code astro-code-themes gruvbox-light-medium gruvbox-dark-medium&quot; style=&quot;--shiki-light:#3c3836;--shiki-dark:#ebdbb2;--shiki-light-bg:#fbf1c7;--shiki-dark-bg:#282828; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;bash&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;--shiki-light:#B57614;--shiki-dark:#FABD2F&quot;&gt;curl&lt;/span&gt;&lt;span style=&quot;--shiki-light:#7C6F64;--shiki-dark:#A89984&quot;&gt; &quot;&lt;/span&gt;&lt;span style=&quot;--shiki-light:#79740E;--shiki-dark:#B8BB26&quot;&gt;http://ip-api.com/json/{IP_ADDRESS}&lt;/span&gt;&lt;span style=&quot;--shiki-light:#7C6F64;--shiki-dark:#A89984&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Record the following fields:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;city&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;regionName&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;country&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;isp&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;as&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;3-query-virustotal-optional-but-recommended&quot;&gt;3. Query VirusTotal (optional but recommended)&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;Web interface:&lt;/strong&gt;&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Go to &lt;a href=&quot;https://virustotal.com&quot;&gt;https://virustotal.com&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Click “Search” and enter the IP address&lt;/li&gt;
&lt;li&gt;Go to the “Details” tab&lt;/li&gt;
&lt;li&gt;Record: Country, ASN, Network&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;strong&gt;API:&lt;/strong&gt;&lt;/p&gt;
&lt;pre class=&quot;astro-code astro-code-themes gruvbox-light-medium gruvbox-dark-medium&quot; style=&quot;--shiki-light:#3c3836;--shiki-dark:#ebdbb2;--shiki-light-bg:#fbf1c7;--shiki-dark-bg:#282828; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;bash&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;--shiki-light:#B57614;--shiki-dark:#FABD2F&quot;&gt;curl&lt;/span&gt;&lt;span style=&quot;--shiki-light:#8F3F71;--shiki-dark:#D3869B&quot;&gt; --header&lt;/span&gt;&lt;span style=&quot;--shiki-light:#7C6F64;--shiki-dark:#A89984&quot;&gt; &quot;&lt;/span&gt;&lt;span style=&quot;--shiki-light:#79740E;--shiki-dark:#B8BB26&quot;&gt;x-apikey: {YOUR_API_KEY}&lt;/span&gt;&lt;span style=&quot;--shiki-light:#7C6F64;--shiki-dark:#A89984&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;--shiki-light:#8F3F71;--shiki-dark:#D3869B&quot;&gt; \&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;--shiki-light:#7C6F64;--shiki-dark:#A89984&quot;&gt;  &quot;&lt;/span&gt;&lt;span style=&quot;--shiki-light:#79740E;--shiki-dark:#B8BB26&quot;&gt;https://www.virustotal.com/api/v3/ip_addresses/{IP_ADDRESS}&lt;/span&gt;&lt;span style=&quot;--shiki-light:#7C6F64;--shiki-dark:#A89984&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Record from &lt;code&gt;data.attributes&lt;/code&gt;:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;country&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;asn&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;as_owner&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;4-check-for-vpnproxytor&quot;&gt;4. Check for VPN/Proxy/Tor&lt;/h3&gt;
&lt;p&gt;This step determines whether the IP is masking its true origin.&lt;/p&gt;
&lt;h4 id=&quot;4a-check-ip-apicom-flags&quot;&gt;4a. Check ip-api.com flags&lt;/h4&gt;
&lt;p&gt;If you queried ip-api.com in Step 2, check these additional fields in the response:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;proxy&lt;/code&gt;: true/false (detects proxy/VPN)&lt;/li&gt;
&lt;li&gt;&lt;code&gt;hosting&lt;/code&gt;: true/false (datacenter/hosting provider, often indicates VPN)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;API (with extra fields):&lt;/strong&gt;&lt;/p&gt;
&lt;pre class=&quot;astro-code astro-code-themes gruvbox-light-medium gruvbox-dark-medium&quot; style=&quot;--shiki-light:#3c3836;--shiki-dark:#ebdbb2;--shiki-light-bg:#fbf1c7;--shiki-dark-bg:#282828; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;bash&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;--shiki-light:#B57614;--shiki-dark:#FABD2F&quot;&gt;curl&lt;/span&gt;&lt;span style=&quot;--shiki-light:#7C6F64;--shiki-dark:#A89984&quot;&gt; &quot;&lt;/span&gt;&lt;span style=&quot;--shiki-light:#79740E;--shiki-dark:#B8BB26&quot;&gt;http://ip-api.com/json/{IP_ADDRESS}?fields=status,country,city,isp,as,proxy,hosting&lt;/span&gt;&lt;span style=&quot;--shiki-light:#7C6F64;--shiki-dark:#A89984&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h4 id=&quot;4b-check-abuseipdb&quot;&gt;4b. Check AbuseIPDB&lt;/h4&gt;
&lt;p&gt;&lt;strong&gt;Web interface:&lt;/strong&gt;&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Go to &lt;a href=&quot;https://abuseipdb.com&quot;&gt;https://abuseipdb.com&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Enter the IP address&lt;/li&gt;
&lt;li&gt;Look for: Usage Type, ISP, and “Is Tor” flag&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;strong&gt;API:&lt;/strong&gt;&lt;/p&gt;
&lt;pre class=&quot;astro-code astro-code-themes gruvbox-light-medium gruvbox-dark-medium&quot; style=&quot;--shiki-light:#3c3836;--shiki-dark:#ebdbb2;--shiki-light-bg:#fbf1c7;--shiki-dark-bg:#282828; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;bash&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;--shiki-light:#B57614;--shiki-dark:#FABD2F&quot;&gt;curl&lt;/span&gt;&lt;span style=&quot;--shiki-light:#8F3F71;--shiki-dark:#D3869B&quot;&gt; -G&lt;/span&gt;&lt;span style=&quot;--shiki-light:#7C6F64;--shiki-dark:#A89984&quot;&gt; &quot;&lt;/span&gt;&lt;span style=&quot;--shiki-light:#79740E;--shiki-dark:#B8BB26&quot;&gt;https://api.abuseipdb.com/api/v2/check&lt;/span&gt;&lt;span style=&quot;--shiki-light:#7C6F64;--shiki-dark:#A89984&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;--shiki-light:#8F3F71;--shiki-dark:#D3869B&quot;&gt; \&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;--shiki-light:#8F3F71;--shiki-dark:#D3869B&quot;&gt;  --data-urlencode&lt;/span&gt;&lt;span style=&quot;--shiki-light:#7C6F64;--shiki-dark:#A89984&quot;&gt; &quot;&lt;/span&gt;&lt;span style=&quot;--shiki-light:#79740E;--shiki-dark:#B8BB26&quot;&gt;ipAddress={IP_ADDRESS}&lt;/span&gt;&lt;span style=&quot;--shiki-light:#7C6F64;--shiki-dark:#A89984&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;--shiki-light:#8F3F71;--shiki-dark:#D3869B&quot;&gt; \&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;--shiki-light:#8F3F71;--shiki-dark:#D3869B&quot;&gt;  -H&lt;/span&gt;&lt;span style=&quot;--shiki-light:#7C6F64;--shiki-dark:#A89984&quot;&gt; &quot;&lt;/span&gt;&lt;span style=&quot;--shiki-light:#79740E;--shiki-dark:#B8BB26&quot;&gt;Key: {YOUR_API_KEY}&lt;/span&gt;&lt;span style=&quot;--shiki-light:#7C6F64;--shiki-dark:#A89984&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;--shiki-light:#8F3F71;--shiki-dark:#D3869B&quot;&gt; \&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;--shiki-light:#8F3F71;--shiki-dark:#D3869B&quot;&gt;  -H&lt;/span&gt;&lt;span style=&quot;--shiki-light:#7C6F64;--shiki-dark:#A89984&quot;&gt; &quot;&lt;/span&gt;&lt;span style=&quot;--shiki-light:#79740E;--shiki-dark:#B8BB26&quot;&gt;Accept: application/json&lt;/span&gt;&lt;span style=&quot;--shiki-light:#7C6F64;--shiki-dark:#A89984&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Record from response:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;data.usageType&lt;/code&gt; (e.g., “Data Center/Web Hosting/Transit”)&lt;/li&gt;
&lt;li&gt;&lt;code&gt;data.isTor&lt;/code&gt; (true/false)&lt;/li&gt;
&lt;li&gt;&lt;code&gt;data.totalReports&lt;/code&gt; (abuse report count)&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 id=&quot;4c-check-tor-exit-node-list&quot;&gt;4c. Check Tor Exit Node List&lt;/h4&gt;
&lt;p&gt;&lt;strong&gt;Manual check:&lt;/strong&gt;&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Download the list: &lt;a href=&quot;https://check.torproject.org/torbulkexitlist&quot;&gt;https://check.torproject.org/torbulkexitlist&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Search for the IP address in the file&lt;/li&gt;
&lt;li&gt;If found, the IP is a known Tor exit node&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;strong&gt;Command line:&lt;/strong&gt;&lt;/p&gt;
&lt;pre class=&quot;astro-code astro-code-themes gruvbox-light-medium gruvbox-dark-medium&quot; style=&quot;--shiki-light:#3c3836;--shiki-dark:#ebdbb2;--shiki-light-bg:#fbf1c7;--shiki-dark-bg:#282828; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;bash&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;--shiki-light:#B57614;--shiki-dark:#FABD2F&quot;&gt;curl&lt;/span&gt;&lt;span style=&quot;--shiki-light:#8F3F71;--shiki-dark:#D3869B&quot;&gt; -s&lt;/span&gt;&lt;span style=&quot;--shiki-light:#7C6F64;--shiki-dark:#A89984&quot;&gt; &quot;&lt;/span&gt;&lt;span style=&quot;--shiki-light:#79740E;--shiki-dark:#B8BB26&quot;&gt;https://check.torproject.org/torbulkexitlist&lt;/span&gt;&lt;span style=&quot;--shiki-light:#7C6F64;--shiki-dark:#A89984&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;--shiki-light:#427B58;--shiki-dark:#8EC07C&quot;&gt; |&lt;/span&gt;&lt;span style=&quot;--shiki-light:#B57614;--shiki-dark:#FABD2F&quot;&gt; grep&lt;/span&gt;&lt;span style=&quot;--shiki-light:#8F3F71;--shiki-dark:#D3869B&quot;&gt; -q&lt;/span&gt;&lt;span style=&quot;--shiki-light:#7C6F64;--shiki-dark:#A89984&quot;&gt; &quot;&lt;/span&gt;&lt;span style=&quot;--shiki-light:#79740E;--shiki-dark:#B8BB26&quot;&gt;{IP_ADDRESS}&lt;/span&gt;&lt;span style=&quot;--shiki-light:#7C6F64;--shiki-dark:#A89984&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;--shiki-light:#7C6F64;--shiki-dark:#A89984&quot;&gt; &amp;amp;&amp;amp;&lt;/span&gt;&lt;span style=&quot;--shiki-light:#AF3A03;--shiki-dark:#FE8019&quot;&gt; echo&lt;/span&gt;&lt;span style=&quot;--shiki-light:#7C6F64;--shiki-dark:#A89984&quot;&gt; &quot;&lt;/span&gt;&lt;span style=&quot;--shiki-light:#79740E;--shiki-dark:#B8BB26&quot;&gt;TOR EXIT NODE&lt;/span&gt;&lt;span style=&quot;--shiki-light:#7C6F64;--shiki-dark:#A89984&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;--shiki-light:#427B58;--shiki-dark:#8EC07C&quot;&gt; ||&lt;/span&gt;&lt;span style=&quot;--shiki-light:#AF3A03;--shiki-dark:#FE8019&quot;&gt; echo&lt;/span&gt;&lt;span style=&quot;--shiki-light:#7C6F64;--shiki-dark:#A89984&quot;&gt; &quot;&lt;/span&gt;&lt;span style=&quot;--shiki-light:#79740E;--shiki-dark:#B8BB26&quot;&gt;Not a Tor exit&lt;/span&gt;&lt;span style=&quot;--shiki-light:#7C6F64;--shiki-dark:#A89984&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h4 id=&quot;summary-privacyanonymization-flags&quot;&gt;Summary: Privacy/Anonymization Flags&lt;/h4&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Check&lt;/th&gt;
&lt;th&gt;Result&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;ip-api proxy flag&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;ip-api hosting flag&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;AbuseIPDB usageType&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;AbuseIPDB isTor&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Tor exit node list&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;&lt;strong&gt;Interpretation:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Tor exit node&lt;/strong&gt;: Location data is meaningless; this is the exit point, not the user&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Proxy/VPN detected&lt;/strong&gt;: Location may be the VPN endpoint, not the user&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Hosting/Datacenter&lt;/strong&gt;: Likely a server, VPN endpoint, or automated traffic—not a typical end user&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;validation&quot;&gt;Validation&lt;/h2&gt;
&lt;p&gt;Compare the results from each source:&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Field&lt;/th&gt;
&lt;th&gt;IPinfo.io&lt;/th&gt;
&lt;th&gt;ip-api.com&lt;/th&gt;
&lt;th&gt;VirusTotal&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Country&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;City/Region&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;ASN/Org&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;&lt;strong&gt;Validation checks:&lt;/strong&gt;&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Country match&lt;/strong&gt;: Do all sources agree on the country?&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;If YES: High confidence in country-level location&lt;/li&gt;
&lt;li&gt;If NO: Flag discrepancy; IP may use anycast or be misattributed&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;City/Region match&lt;/strong&gt;: Do at least 2 sources agree on city or region?&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;If YES: Reasonable confidence in city-level location&lt;/li&gt;
&lt;li&gt;If NO: Report country only; city-level data is unreliable for this IP&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;ASN/Org match&lt;/strong&gt;: Do the ASN numbers match?&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;If YES: Confirms the network owner&lt;/li&gt;
&lt;li&gt;If NO: Investigate further; one source may have stale data&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;strong&gt;Known limitations:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;VPNs, proxies, and Tor exit nodes will show the endpoint location, not the user (Step 4 helps detect these)&lt;/li&gt;
&lt;li&gt;CDN and anycast IPs (e.g., Cloudflare, Google) may return multiple valid locations&lt;/li&gt;
&lt;li&gt;Mobile IPs may geolocate to carrier headquarters, not actual user location&lt;/li&gt;
&lt;li&gt;Privacy detection is not perfect; some VPNs use residential IPs that evade detection&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;output&quot;&gt;Output&lt;/h2&gt;
&lt;p&gt;Produce a summary in this format:&lt;/p&gt;
&lt;pre class=&quot;astro-code astro-code-themes gruvbox-light-medium gruvbox-dark-medium&quot; style=&quot;--shiki-light:#3c3836;--shiki-dark:#ebdbb2;--shiki-light-bg:#fbf1c7;--shiki-dark-bg:#282828; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;plaintext&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span&gt;IP Address: {IP}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;Lookup Date: {YYYY-MM-DD}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;Location:&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  Country: {country} (confidence: high/medium/low)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  City/Region: {city, region} (confidence: high/medium/low)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;Network:&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  ASN: {asn}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  Organization: {org name}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;Privacy/Anonymization:&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  Tor Exit Node: {yes/no}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  Proxy/VPN Detected: {yes/no/unknown}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  Hosting/Datacenter: {yes/no}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  ⚠️ Location Reliability: {reliable / unreliable - anonymized}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;Validation:&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  Sources queried: {list sources}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  Country consensus: {yes/no}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  City consensus: {yes/no}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;Notes:&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  {any discrepancies or flags}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;Important:&lt;/strong&gt; If any privacy/anonymization flag is positive, add a warning that the geolocation data represents the proxy/VPN/Tor endpoint, NOT the actual user location.&lt;/p&gt;
&lt;h2 id=&quot;logging&quot;&gt;Logging&lt;/h2&gt;
&lt;p&gt;Record the following in your investigation log or ticket:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;The IP address queried&lt;/li&gt;
&lt;li&gt;Date/time of lookup&lt;/li&gt;
&lt;li&gt;Sources consulted&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Location results&lt;/strong&gt;: Country, City/Region, confidence level&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Network info&lt;/strong&gt;: ASN, Organization&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Privacy flags&lt;/strong&gt;: Tor, Proxy/VPN, Hosting/Datacenter&lt;/li&gt;
&lt;li&gt;Location reliability assessment&lt;/li&gt;
&lt;li&gt;Any discrepancies noted&lt;/li&gt;
&lt;li&gt;Analyst name or “automated” if run by script&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;strong&gt;Example log entry:&lt;/strong&gt;&lt;/p&gt;
&lt;pre class=&quot;astro-code astro-code-themes gruvbox-light-medium gruvbox-dark-medium&quot; style=&quot;--shiki-light:#3c3836;--shiki-dark:#ebdbb2;--shiki-light-bg:#fbf1c7;--shiki-dark-bg:#282828; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;plaintext&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span&gt;[2026-01-01 14:30] GeoIP lookup for 203.0.113.42&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;Sources: IPinfo.io, ip-api.com, VirusTotal, AbuseIPDB, Tor list&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;Result: Netherlands, Amsterdam (high confidence)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;ASN: AS12345 - Example Hosting Inc.&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;Privacy: Not Tor, no proxy detected, hosting=yes (datacenter IP)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;Notes: All geo sources agree. Datacenter IP suggests server or VPN endpoint.&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;Analyst: AJ&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id=&quot;automation-notes&quot;&gt;Automation Notes&lt;/h2&gt;
&lt;p&gt;This playbook is a good candidate for scripting because:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;All steps are deterministic&lt;/li&gt;
&lt;li&gt;APIs return structured data&lt;/li&gt;
&lt;li&gt;Validation logic is straightforward&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;A script should:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Accept IP as input&lt;/li&gt;
&lt;li&gt;Query all configured sources&lt;/li&gt;
&lt;li&gt;Compare results automatically&lt;/li&gt;
&lt;li&gt;Output the summary format above&lt;/li&gt;
&lt;li&gt;Flag discrepancies for human review&lt;/li&gt;
&lt;/ol&gt;</content:encoded><ajvb:lane>playbooks</ajvb:lane><ajvb:maturity>evergreen</ajvb:maturity><ajvb:markdown>https://ajvanbeest.com/playbooks/geoip-lookup.md</ajvb:markdown><ajvb:json>https://ajvanbeest.com/playbooks/geoip-lookup.json</ajvb:json><category>security</category><category>playbooks</category><category>geoip</category><category>osint</category><category>investigation</category></item></channel></rss>