IP Geolocation

Resolve any IPv4 / IPv6 address or domain name to a rich geolocation payload — country, region, city, lat/long, postal, currency, ASN, company, timezone, security signals, abuse contact, and user-agent enrichment. Includes single lookup (GET /v3/ipgeo) and bulk lookup (POST /v3/ipgeo-bulk, up to 50,000 entries per request, paid plans).

OpenAPI Specification

ipgeolocation-ip-location-openapi.yml Raw ↑
openapi: 3.0.7
info:
  title: 'IPGeolocation.io: IPGeolocation API'
  version: "3.0"
  description: |
    Look up geolocation, network, company, ASN, timezone, currency, abuse contact, and security
    threat data for any IPv4 address, IPv6 address, or domain name. The API also parses
    User-Agent strings when requested.

    Two endpoints are available:

    - **Single lookup** (`GET /v3/ipgeo`) returns data for one IP or domain per request.
    - **Bulk lookup** (`POST /v3/ipgeo-bulk`) accepts up to 50,000 IPs or domains in a
      single request. Requires a paid plan.

    Use query parameters to control which optional modules are included, which fields are
    returned, and which fields are excluded. Both endpoints share the same query parameters
    and the same response schema per IP.

    ## Authentication

    Two authentication methods are supported:

    ### API Key

    Pass your API key as the `apiKey` query parameter on every request. You can find your
    key in the [IPGeolocation dashboard](https://app.ipgeolocation.io/). Store it in
    server-side environment variables. Avoid exposing it in client-side JavaScript.

    ### Request Origin (CORS)

    Available on paid plans only. Whitelist your domain in the dashboard under the
    "API Keys" section. Once configured, requests from that domain (and all its subdomains)
    are accepted without passing `apiKey`. Enter your root domain (e.g. `example.com`),
    not the full URL.

    Each plan has a limit on the number of extra API keys and request origins:

    | Plan | Extra API Keys + Request Origins |
    |---|---|
    | Starter (150K requests) | 1 |
    | Core (250K requests) | 1 |
    | Plus (500K requests) | 2 |
    | Pro (1M requests) | 2 |
    | Business (2M requests) | 3 |
    | Premium (5M requests) | 3 |

    Additional keys or origins can be added for $2.50 per month each.

    ## Response Formats

    The API supports JSON (default) and XML output.

    - Set the `output` query parameter to `json` or `xml`.
    - Alternatively, set the `Accept` header to `application/json`, `application/xml`,
      or `text/xml`.

    If neither is specified, the response is returned as JSON. XML responses use a
    `LinkedHashMap` root element.

    ## Credits

    Credits are charged only on successful HTTP 200 responses. The exact charge for any
    request is returned in the `X-Credits-Charged` response header.

    | Condition | Credits charged |
    |---|---|
    | Base lookup (location, ASN, company, network, currency, timezone) | 1 |
    | Adding `dma_code`, `geo_accuracy`, `hostname`, or `user_agent` | 0 extra (still 1) |
    | Adding `security` | +2 (total 3) |
    | Adding `abuse` | +1 (total 2) |
    | Adding `security` and `abuse` | +3 (total 4) |
    | `include=*` (everything) | 4 |
    | Only `security` via `include=security&fields=security` | 2 |
    | Only `abuse` via `include=abuse&fields=abuse` | 1 |

    For bulk requests, total credits equal credits per lookup multiplied by the number of
    valid IPs. Private, bogon, and malformed IPs are not counted as valid and do not
    consume credits.

    ## Response Language

    Pass `lang` to get translated location names. English is the default. Non-English
    responses require a paid plan.

    ## Field Filtering

    Use `fields` to cherry-pick specific fields, or `excludes` to drop fields you do not
    need. Both accept dot-notation for nested fields (e.g. `location.city`,
    `security.threat_score`). The `ip` field is always present regardless of filters.

    ## Parameter Name Casing

    Query parameter names are case-sensitive. Use exact names such as `apiKey`, `ip`,
    `include`, `fields`, `excludes`, `lang`, and `output`.

    ## Rate Limits

    - **Free plan:** 1,000 requests per day (hard limit).
    - **Paid plans:** No daily, hourly, or monthly rate limit. If the monthly quota is
      exceeded, requests continue and a surcharge is added to the monthly bill.

    ## Free vs. Paid Plan Differences

    | Capability | Free | Paid |
    |---|---|---|
    | IPv4 / IPv6 lookup | Yes | Yes |
    | Domain lookup | No | Yes |
    | Bulk lookup (`/v3/ipgeo-bulk`) | No | Yes |
    | `include` parameter (optional modules) | No | Yes |
    | `lang` (non-English responses) | No | Yes |
    | `fields` / `excludes` filtering | Yes | Yes |
    | `network` object in default response | No | Yes |
    | `company` object in default response | No | Yes |
    | Basic `asn` fields (`as_number`, `organization`, `country`) | Yes | Yes |
    | Extended `asn` fields (`type`, `domain`, `rir`, `date_allocated`) | No | Yes |
  contact:
    name: IPGeolocation Support
    url: https://ipgeolocation.io/contact.html
    email: [email protected]
  termsOfService: https://ipgeolocation.io/tos.html
  license:
    name: Proprietary
    url: https://ipgeolocation.io/tos.html

externalDocs:
  description: IPGeolocation IP Location API documentation
  url: https://ipgeolocation.io/documentation/ip-location-api.html

servers:
- url: https://api.ipgeolocation.io
  description: Production
security:
- ApiKeyAuth: []
paths:
  /v3/ipgeo:
    get:
      operationId: lookupIpGeolocation
      summary: IPGeolocation.io Single IP Geolocation Lookup
      description: |
        Returns geolocation and enrichment data for a single IPv4 address, IPv6 address,
        or domain name. When `ip` is omitted, the API resolves the caller's public IP
        automatically, which is useful for client-side lookups.

        The base response always includes `location`, `country_metadata`, `currency`,
        `asn`, and `time_zone`. Paid plans also get `network` and `company` by default.

        Use the `include` parameter to add optional modules such as `security`, `abuse`,
        `user_agent`, `geo_accuracy`, `dma_code`, and hostname resolution.

        Use `fields` and `excludes` to control exactly which parts of the response you
        receive. This reduces payload size and can improve response times.
      tags:
      - IP Geolocation
      parameters:
      - $ref: "#/components/parameters/Ip"
      - $ref: "#/components/parameters/Lang"
      - $ref: "#/components/parameters/Include"
      - $ref: "#/components/parameters/Fields"
      - $ref: "#/components/parameters/Excludes"
      - $ref: "#/components/parameters/Output"
      responses:
        "200":
          description: Geolocation data for the requested IP or domain.
          headers:
            X-Credits-Charged:
              description: Number of API credits consumed by this request.
              schema:
                type: number
                example: 1
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/IpGeolocationResponse"
              examples:
                paidFullResponse:
                  summary: Paid plan, all modules included
                  value:
                    ip: "91.128.103.196"
                    hostname: "91.128.103.196"
                    location:
                      continent_code: "EU"
                      continent_name: "Europe"
                      country_code2: "SE"
                      country_code3: "SWE"
                      country_name: "Sweden"
                      country_name_official: "Kingdom of Sweden"
                      country_capital: "Stockholm"
                      state_prov: "Stockholms län"
                      state_code: "SE-AB"
                      district: "Stockholm"
                      city: "Stockholm"
                      locality: "Stockholm"
                      accuracy_radius: "4.395"
                      confidence: "high"
                      dma_code: ""
                      zipcode: "164 40"
                      latitude: "59.40510"
                      longitude: "17.95510"
                      is_eu: true
                      country_flag: "https://ipgeolocation.io/static/flags/se_64.png"
                      geoname_id: "9972319"
                      country_emoji: "🇸🇪"
                    country_metadata:
                      calling_code: "+46"
                      tld: ".se"
                      languages:
                      - "sv-SE"
                      - "se"
                      - "sma"
                      - "fi-SE"
                    network:
                      connection_type: ""
                      route: "91.128.0.0/14"
                      is_anycast: false
                    currency:
                      code: "SEK"
                      name: "Swedish Krona"
                      symbol: "kr"
                    asn:
                      as_number: "AS1257"
                      organization: "Tele2 Sverige AB"
                      country: "SE"
                      type: "ISP"
                      domain: "tele2.com"
                      date_allocated: "2024-12-13"
                      rir: "RIPE"
                    company:
                      name: "Tele2 Sverige AB"
                      type: "ISP"
                      domain: "tele2.com"
                    security:
                      threat_score: 0
                      is_tor: false
                      is_proxy: false
                      proxy_provider_names: []
                      proxy_confidence_score: 0
                      proxy_last_seen: ""
                      is_residential_proxy: false
                      is_vpn: false
                      vpn_provider_names: []
                      vpn_confidence_score: 0
                      vpn_last_seen: ""
                      is_relay: false
                      relay_provider_name: ""
                      is_anonymous: false
                      is_known_attacker: false
                      is_bot: false
                      is_spam: false
                      is_cloud_provider: false
                      cloud_provider_name: ""
                    abuse:
                      route: "91.128.0.0/14"
                      country: "SE"
                      name: "Swipnet Staff"
                      organization: ""
                      kind: "group"
                      address: "Tele2 AB/Swedish IP Network, IP Registry, Torshamnsgatan 17 164 40 Kista SWEDEN"
                      emails:
                      - "[email protected]"
                      phone_numbers:
                      - "+46 8 5626 42 10"
                    time_zone:
                      name: "Europe/Stockholm"
                      offset: 1
                      offset_with_dst: 1
                      current_time: "2026-02-13 09:19:24.410+0100"
                      current_time_unix: 1770970764.41
                      current_tz_abbreviation: "CET"
                      current_tz_full_name: "Central European Standard Time"
                      standard_tz_abbreviation: "CET"
                      standard_tz_full_name: "Central European Standard Time"
                      is_dst: false
                      dst_savings: 0
                      dst_exists: true
                      dst_tz_abbreviation: "CEST"
                      dst_tz_full_name: "Central European Summer Time"
                      dst_start:
                        utc_time: "2026-03-29 TIME 01:00"
                        duration: "+1.00H"
                        gap: true
                        date_time_after: "2026-03-29 TIME 03:00"
                        date_time_before: "2026-03-29 TIME 02:00"
                        overlap: false
                      dst_end:
                        utc_time: "2026-10-25 TIME 01:00"
                        duration: "-1.00H"
                        gap: false
                        date_time_after: "2026-10-25 TIME 02:00"
                        date_time_before: "2026-10-25 TIME 03:00"
                        overlap: true
                    user_agent:
                      user_agent_string: "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/143.0.0.0 Safari/537.36 Edg/143.0.0.0"
                      name: "Edge"
                      type: "Browser"
                      version: "143"
                      version_major: "143"
                      device:
                        name: "Linux Desktop"
                        type: "Desktop"
                        brand: "Unknown"
                        cpu: "Intel x86_64"
                      engine:
                        name: "Blink"
                        type: "Browser"
                        version: "143"
                        version_major: "143"
                      operating_system:
                        name: "Linux"
                        type: "Desktop"
                        version: "??"
                        version_major: "??"
                        build: "??"
                freeMinimalResponse:
                  summary: Free plan default response
                  value:
                    ip: "165.227.0.0"
                    location:
                      continent_code: "NA"
                      continent_name: "North America"
                      country_code2: "US"
                      country_code3: "USA"
                      country_name: "United States"
                      country_name_official: "United States of America"
                      country_capital: "Washington, D.C."
                      state_prov: "California"
                      state_code: "US-CA"
                      district: "Santa Clara County"
                      city: "Santa Clara"
                      zipcode: "95051"
                      latitude: "37.35983"
                      longitude: "-121.98144"
                      is_eu: false
                      country_flag: "https://ipgeolocation.io/static/flags/us_64.png"
                      geoname_id: "5346804"
                      country_emoji: "🇺🇸"
                    country_metadata:
                      calling_code: "+1"
                      tld: ".us"
                      languages:
                      - "en-US"
                      - "es-US"
                      - "haw"
                      - "fr"
                    currency:
                      code: "USD"
                      name: "US Dollar"
                      symbol: "$"
                    asn:
                      as_number: "AS14061"
                      organization: "DigitalOcean, LLC"
                      country: "US"
                    time_zone:
                      name: "America/Los_Angeles"
                      offset: -8
                      offset_with_dst: -8
                      current_time: "2026-02-09 09:54:51.206-0800"
                      current_time_unix: 1770659691.206
                      current_tz_abbreviation: "PST"
                      current_tz_full_name: "Pacific Standard Time"
                      standard_tz_abbreviation: "PST"
                      standard_tz_full_name: "Pacific Standard Time"
                      is_dst: false
                      dst_savings: 0
                      dst_exists: true
                      dst_tz_abbreviation: "PDT"
                      dst_tz_full_name: "Pacific Daylight Time"
                      dst_start:
                        utc_time: "2026-03-08 TIME 10:00"
                        duration: "+1.00H"
                        gap: true
                        date_time_after: "2026-03-08 TIME 03:00"
                        date_time_before: "2026-03-08 TIME 02:00"
                        overlap: false
                      dst_end:
                        utc_time: "2026-11-01 TIME 09:00"
                        duration: "-1.00H"
                        gap: false
                        date_time_after: "2026-11-01 TIME 01:00"
                        date_time_before: "2026-11-01 TIME 02:00"
                        overlap: true
            application/xml:
              schema:
                $ref: "#/components/schemas/IpGeolocationResponse"
              examples:
                paidFullResponse:
                  summary: Paid plan, all modules included (XML)
                  value: |
                    <LinkedHashMap>
                      <ip>91.128.103.196</ip>
                      <hostname>91.128.103.196</hostname>
                      <location>
                          <continent_code>EU</continent_code>
                          <continent_name>Europe</continent_name>
                          <country_code2>SE</country_code2>
                          <country_code3>SWE</country_code3>
                          <country_name>Sweden</country_name>
                          <country_name_official>Kingdom of Sweden</country_name_official>
                          <country_capital>Stockholm</country_capital>
                          <state_prov>Stockholms län</state_prov>
                          <state_code>SE-AB</state_code>
                          <district>Stockholm</district>
                          <city>Stockholm</city>
                          <locality>Stockholm</locality>
                          <accuracy_radius>8.793</accuracy_radius>
                          <confidence>high</confidence>
                          <dma_code></dma_code>
                          <zipcode>164 40</zipcode>
                          <latitude>59.40510</latitude>
                          <longitude>17.95510</longitude>
                          <is_eu>true</is_eu>
                          <country_flag>https://ipgeolocation.io/static/flags/se_64.png</country_flag>
                          <geoname_id>9972319</geoname_id>
                          <country_emoji>🇸🇪</country_emoji>
                      </location>
                      <country_metadata>
                          <calling_code>+46</calling_code>
                          <tld>.se</tld>
                          <languages>sv-SE</languages>
                          <languages>se</languages>
                          <languages>sma</languages>
                          <languages>fi-SE</languages>
                      </country_metadata>
                      <network>
                          <connection_type></connection_type>
                          <route>91.128.0.0/14</route>
                          <is_anycast>false</is_anycast>
                      </network>
                      <currency>
                          <code>SEK</code>
                          <name>Swedish Krona</name>
                          <symbol>kr</symbol>
                      </currency>
                      <asn>
                          <as_number>AS1257</as_number>
                          <organization>Tele2 Sverige AB</organization>
                          <country>SE</country>
                          <type>ISP</type>
                          <domain>tele2.com</domain>
                          <date_allocated>2002-09-19</date_allocated>
                          <rir>RIPE</rir>
                      </asn>
                      <company>
                          <name>Tele2 Sverige AB</name>
                          <type>ISP</type>
                          <domain>tele2.com</domain>
                      </company>
                      <security>
                          <threat_score>0</threat_score>
                          <is_tor>false</is_tor>
                          <is_proxy>false</is_proxy>
                          <proxy_confidence_score>0</proxy_confidence_score>
                          <proxy_last_seen></proxy_last_seen>
                          <is_residential_proxy>false</is_residential_proxy>
                          <is_vpn>false</is_vpn>
                          <vpn_confidence_score>0</vpn_confidence_score>
                          <vpn_last_seen></vpn_last_seen>
                          <is_relay>false</is_relay>
                          <relay_provider_name></relay_provider_name>
                          <is_anonymous>false</is_anonymous>
                          <is_known_attacker>false</is_known_attacker>
                          <is_bot>false</is_bot>
                          <is_spam>false</is_spam>
                          <is_cloud_provider>false</is_cloud_provider>
                          <cloud_provider_name></cloud_provider_name>
                      </security>
                      <abuse>
                          <route>91.128.0.0/14</route>
                          <country>SE</country>
                          <name>Swipnet Staff</name>
                          <organization></organization>
                          <kind>group</kind>
                          <address>Tele2 AB/Swedish IP Network, IP Registry, Torshamnsgatan 17 164 40 Kista SWEDEN</address>
                          <emails>[email protected]</emails>
                          <phone_numbers>+46 8 5626 42 10</phone_numbers>
                      </abuse>
                      <time_zone>
                          <name>Europe/Stockholm</name>
                          <offset>1</offset>
                          <offset_with_dst>1</offset_with_dst>
                          <current_time>2026-03-02 13:32:39.256+0100</current_time>
                          <current_time_unix>1772454759.256</current_time_unix>
                          <current_tz_abbreviation>CET</current_tz_abbreviation>
                          <current_tz_full_name>Central European Standard Time</current_tz_full_name>
                          <standard_tz_abbreviation>CET</standard_tz_abbreviation>
                          <standard_tz_full_name>Central European Standard Time</standard_tz_full_name>
                          <is_dst>false</is_dst>
                          <dst_savings>0</dst_savings>
                          <dst_exists>true</dst_exists>
                          <dst_tz_abbreviation>CEST</dst_tz_abbreviation>
                          <dst_tz_full_name>Central European Summer Time</dst_tz_full_name>
                          <dst_start>
                              <utc_time>2026-03-29 TIME 01:00</utc_time>
                              <duration>+1.00H</duration>
                              <gap>true</gap>
                              <date_time_after>2026-03-29 TIME 03:00</date_time_after>
                              <date_time_before>2026-03-29 TIME 02:00</date_time_before>
                              <overlap>false</overlap>
                          </dst_start>
                          <dst_end>
                              <utc_time>2026-10-25 TIME 01:00</utc_time>
                              <duration>-1.00H</duration>
                              <gap>false</gap>
                              <date_time_after>2026-10-25 TIME 02:00</date_time_after>
                              <date_time_before>2026-10-25 TIME 03:00</date_time_before>
                              <overlap>true</overlap>
                          </dst_end>
                      </time_zone>
                      <user_agent>
                          <user_agent_string>PostmanRuntime/7.49.1</user_agent_string>
                          <name>PostmanRuntime</name>
                          <type>Robot</type>
                          <version>7.49.1</version>
                          <version_major>7</version_major>
                          <device>
                              <name>Postman Runtime</name>
                              <type>Robot</type>
                              <brand>Postman</brand>
                              <cpu>Unknown</cpu>
                          </device>
                          <engine>
                              <name>PostmanRuntime</name>
                              <type>Robot</type>
                              <version>7.49.1</version>
                              <version_major>7</version_major>
                          </engine>
                          <operating_system>
                              <name>Cloud</name>
                              <type>Cloud</type>
                              <version>??</version>
                              <version_major>??</version_major>
                              <build>??</build>
                          </operating_system>
                      </user_agent>
                    </LinkedHashMap>

                freeMinimalResponse:
                  summary: Free plan default response (XML)
                  value: |
                    <LinkedHashMap>
                      <ip>165.227.0.0</ip>
                      <location>
                          <continent_code>NA</continent_code>
                          <continent_name>North America</continent_name>
                          <country_code2>US</country_code2>
                          <country_code3>USA</country_code3>
                          <country_name>United States</country_name>
                          <country_name_official>United States of America</country_name_official>
                          <country_capital>Washington, D.C.</country_capital>
                          <state_prov>California</state_prov>
                          <state_code>US-CA</state_code>
                          <district>Santa Clara County</district>
                          <city>Santa Clara</city>
                          <zipcode>95051</zipcode>
                          <latitude>37.35983</latitude>
                          <longitude>-121.98144</longitude>
                          <is_eu>false</is_eu>
                          <country_flag>https://ipgeolocation.io/static/flags/us_64.png</country_flag>
                          <geoname_id>5346804</geoname_id>
                          <country_emoji>🇺🇸</country_emoji>
                      </location>
                      <country_metadata>
                          <calling_code>+1</calling_code>
                          <tld>.us</tld>
                          <languages>en-US</languages>
                          <languages>es-US</languages>
                          <languages>haw</languages>
                          <languages>fr</languages>
                      </country_metadata>
                      <currency>
                          <code>USD</code>
                          <name>US Dollar</name>
                          <symbol>$</symbol>
                      </currency>
                      <asn>
                          <as_number>AS14061</as_number>
                          <organization>DigitalOcean, LLC</organization>
                          <country>US</country>
                      </asn>
                      <time_zone>
                          <name>America/Los_Angeles</name>
                          <offset>-8</offset>
                          <offset_with_dst>-8</offset_with_dst>
                          <current_time>2026-03-02 03:29:55.186-0800</current_time>
                          <current_time_unix>1772450995.186</current_time_unix>
                          <current_tz_abbreviation>PST</current_tz_abbreviation>
                          <current_tz_full_name>Pacific Standard Time</current_tz_full_name>
                          <standard_tz_abbreviation>PST</standard_tz_abbreviation>
                          <standard_tz_full_name>Pacific Standard Time</standard_tz_full_name>
                          <is_dst>false</is_dst>
                          <dst_savings>0</dst_savings>
                          <dst_exists>true</dst_exists>
                          <dst_tz_abbreviation>PDT</dst_tz_abbreviation>
                          <dst_tz_full_name>Pacific Daylight Time</dst_tz_full_name>
                          <dst_start>
                              <utc_time>2026-03-08 TIME 10:00</utc_time>
                              <duration>+1.00H</duration>
                              <gap>true</gap>
                              <date_time_after>2026-03-08 TIME 03:00</date_time_after>
                              <date_time_before>2026-03-08 TIME 02:00</date_time_before>
                              <overlap>false</overlap>
                          </dst_start>
                          <dst_end>
                              <utc_time>2026-11-01 TIME 09:00</utc_time>
                              <duration>-1.00H</duration>
                              <gap>false</gap>
                              <date_time_after>2026-11-01 TIME 01:00</date_time_after>
                              <date_time_before>2026-11-01 TIME 02:00</date_time_before>
                              <overlap>true</overlap>
                          </dst_end>
                      </time_zone>
                    </LinkedHashMap>

        "400":
          $ref: "#/components/responses/BadRequest"
        "401":
          $ref: "#/components/responses/Unauthorized"
        "404":
          $ref: "#/components/responses/NotFound"
        "405":
          $ref: "#/components/responses/MethodNotAllowed"
        "423":
          $ref: "#/components/responses/Locked"
        "429":
          $ref: "#/components/responses/TooManyRequests"
        "499":
          $ref: "#/components/responses/ClientClosedRequest"
        "500":
          $ref: "#/components/responses/InternalServerError"
        "502":
          $ref: "#/components/responses/BadGateway"
        "503":
          $ref: "#/components/responses/ServiceUnavailable"
        "504":
          $ref: "#/components/responses/GatewayTimeout"
        "505":
          $ref: "#/components/responses/HttpVersionNotSupported"

      x-microcks-operation:
        delay: 0
        dispatcher: FALLBACK
  /v3/ipgeo-bulk:
    post:
      operationId: bulkLookupIpGeolocation
      summary: IPGeolocation.io Bulk IP Geolocation Lookup
      description: |
        Returns geolocation and enrichment data for up to 50,000 IPv4 addresses, IPv6
        addresses, or domain names in a single request. The request body must be a JSON
        object with an `ips` array.

        This endpoint requires a paid plan. Calling it with a free
        plan API key returns HTTP 401.

        The response is a JSON array with one element per IP in the request. Each element
        is either a full geolocation response object or an error object with only a
        `message` field. Invalid, bogon, and unresolvable entries appear as error
        objects. Invalid, private, and bogon IPs are not billed.

        This endpoint supports the same query parameters as the single lookup endpoint,
        including `lang`, `include`, `fields`, `excludes`, and `output`.

        Credits are calculated as: credits per lookup multiplied by the number of valid
        IPs in the request. The total is returned in the `X-Credits-Charged` response
        header. When at least one submitted ip is invalid, the `X-Successful-Record`
        response header indicates how many entries were successfully resolved.

        Only the `POST` method is accepted. Sending a `GET` request returns HTTP 405.
      tags:
      - IP Geolocation
      parameters:
      - $ref: "#/components/parameters/Lang"
      - $ref: "#/components/parameters/Include"
      - $ref: "#/components/parameters/Fields"
      - $ref: "#/components/parameters/Excludes"
      - $ref: "#/components/parameters/Output"
      requestBody:
        required: true
        description: |
          A JSON object containing an `ips` array. Each element is a string representing
          an IPv4 address, IPv6 address, or domain name. The array must not be empty and
          must not contain more than 50,000 entries.
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/BulkGeolocationRequest"
            examples:
              mixedIps:
                summary: Mixed IPv4, IPv6, and domain
                value:
                  ips:
                  - "8.8.8.8"
                  - "91.128.103.196"
                  - "2607:fb91:16c6:8860:e531:2d1d:4944:6c7c"
                  - "ipgeolocation.io"
              ipv4Only:
                summary: Multiple IPv4 addresses
                value:
                  ips:
                  - "1.1.1.1"
                  - "8.8.4.4"
                  - "165.227.0.0"
      responses:
        "200":
          description: |
            An array of results, one per input entry. Valid entries return full
            geolocation objects. Invalid, bogon, and unresolvable entries return
            objects with only a `message` field.
            `X-Successful-Record` is returned only when at least one submitted entry
            fails and the number of successful lookups is lower than the number of
            submitted entries.
          headers:
            X-Credit

# --- truncated at 32 KB (92 KB total) ---
# Full source: https://raw.githubusercontent.com/api-evangelist/ipgeolocation/refs/heads/main/openapi/ipgeolocation-ip-location-openapi.yml