# ipinfo: the official Python client for the IPinfo.io API

> ipinfo is IPinfo's own Python client for looking up IP addresses, covering geolocation, ASN details, firmographics and carrier data across four API tiers. The library exposes a synchronous handler, an asyncio handler and Lite, Core and Plus variants, and it needs an access token to return anything beyond the free tier's field set.

**ipinfo/python** — Official Python Library for IPinfo API (IP geolocation and other types of IP data)

- Repository: https://github.com/ipinfo/python
- Website: https://ipinfo.io
- Stars: 568 · Forks: 127
- Language: Python
- License: Apache-2.0
- Published: 2026-10-22 · Updated: 2026-10-22 · Language: en
- Canonical page: https://hysenlabs.com/projects/ipinfo-python

## What a lookup actually returns

The library covers four families of data, and the README lists the fields for each. IP geolocation gives city, region, country, postal code, latitude and longitude. ASN details give the ISP or network operator, the associated domain name, and the type, such as business, hosting or company. Firmographics data gives the name and domain of the business that uses the IP address, and carrier information gives the name of the mobile carrier and the MNC and MCC for that carrier if the IP is used exclusively for mobile traffic. The response object is a Details instance, and the README says it contains all fields listed in the IPinfo developer docs with a few minor additions, accessed directly as properties. The full response, obtainable through details.all as a dictionary, is a nested structure with keys for abuse contact details, the asn block, city, company, country and country name, hosting, hostname, the ip itself, latitude and loc and longitude, postal, region and timezone.

## Installing it and making a first lookup

The package is installed with pip:

```bash
pip install ipinfo
```

The README notes that this package works with Python 3.5 or greater, but that only non-EOL Python versions are officially supported, and the project metadata in pyproject.toml is stricter, requiring Python 3.10 or newer, which is the number to plan against. The quick start is a four-step sequence, and you need an access token from a free account before any of it works:

```python
>>> import ipinfo
>>> access_token = '123456789abc'
>>> handler = ipinfo.getHandler(access_token)
>>> ip_address = '216.239.36.21'
>>> details = handler.getDetails(ip_address)
>>> details.city
'Mountain View'
>>> details.loc
'37.3861,-122.0840'
```

The token can be passed positionally or by keyword, and the library also works without an authentication token but in a more limited capacity, which is the detail that decides whether your chosen plan matters to the code you write.

## Looking up the caller's own address

The getDetails method accepts an IP address as an optional, positional argument, and if no IP address is specified the API returns data for the IP address from which it receives the request. That is the call that makes a library worth having, since the server-side address is the one your application usually cares about:

```python
>>> import ipinfo
>>> access_token = '123456789abc'
>>> handler = ipinfo.getHandler(access_token)
>>> details = handler.getDetails()
>>> details.city
'Mountain View'
>>> details.loc
'37.3861,-122.0840'
```

The Details object is also where a few field-level conventions show up. details.country_name returns the country name as supplied by the countries.json file, while details.country still returns the country code, and the README points to that file for instructions on changing it for use with non-English languages. The latitude and longitude properties return the two values as separate strings, while details.loc returns the composite string of both. The whole response is available as a dictionary through details.all, which is what you would dump when you need a field the library does not expose as a property.

## Four API tiers behind one handler

The library is organised around API tiers, and each has its own handler constructor. The base handler covers the standard response, the Lite API has its own getHandlerLite, and the README says the returned details are slightly different from the Core API. The Core API provides city-level geolocation with nested geo and AS objects, and it can be created with getHandlerCore:

```python
>>> import ipinfo
>>> handler = ipinfo.getHandlerCore(access_token='123456789abc')
>>> details = handler.getDetails("8.8.8.8")
>>> details.ip
'8.8.8.8'
>>> details.geo
{'city': 'Mountain View', 'region': 'California', 'region_code': 'CA', 'country': 'United States', 'country_code': 'US', ...}
```

The Plus API provides enhanced data including mobile carrier info and privacy detection, and the README is cut off before its example, so the constructor for it is not visible in the version available here. What is visible is the pattern: a getHandler variant per tier, each taking the token as a keyword argument, each returning the same Details shape. The Lite tier still requires authentication with your token, which is worth noting because the Lite API is positioned as the cheap one.

## The async handler, and the Python versions it works on

An asynchronous handler is available and is used in almost the same way as the synchronous one, obtained with getHandlerAsync. Internally the library uses aiohttp, but as the README says, as long as you provide an event loop it should not matter:

```python
>>> import ipinfo
>>> access_token = '123456789abc'
>>> handler = ipinfo.getHandlerAsync(access_token)
>>> ip_address = '216.239.36.21'
>>> async def do_req():
...     details = await handler.getDetails(ip_address)
...     print(details.city)
...     print(details.loc)
...
>>>
>>> import asyncio
>>> loop = asyncio.get_event_loop()
>>> loop.run_until_complete(do_req())
Mountain View
37.4056,-122.0775
```

There is also an async Core variant, getHandlerAsyncCore, used the same way. The caveat is a version constraint, and it is a narrow one: due to API changes in the asyncio library, the asynchronous implementation only supports Python version 3.9 and 3.10. That sits awkwardly against the project metadata, which requires Python 3.10 or newer, so on a current Python you are choosing between the synchronous handler and the async one, since the async path is documented for 3.9 and 3.10 only.

## Pricing and the fields the free tier withholds

The commercial reality of this library is in the README's Getting Started section. The free plan is limited to 50,000 requests per month and does not include some of the data fields such as IP type and company data, and the README points at the pricing page for enabling all the data fields and additional request volumes. That has a direct effect on code. A service that resolves a few hundred IPs a day fits comfortably inside the free plan, but an application that looks up every inbound request, or every address in a dataset, will not, and the fix is a plan change rather than a code change. The dependency list shows the same shape of design. The three runtime dependencies are requests, cachetools and aiohttp: requests for the synchronous path, aiohttp for the asynchronous one, and cachetools for caching, which is a reasonable thing to find in a client whose main cost is a billable request.

## Where this client is the wrong choice

Three limits are worth naming. The first is that it is a client for a hosted service, so an air-gapped or privacy-constrained deployment has no path here at all, and the alternative approach in that case is a self-hosted IP geolocation database, which is a different dependency with its own update cadence and its own licence to think about. The second is the async version's Python ceiling, since 3.9 and 3.10 only, which on a modern codebase means the synchronous handler is the realistic choice and the async one is a compatibility liability rather than an option. The third is the data itself. An IP address is a weak signal: carrier and hosting information in particular describes the network an address sits on rather than the person using it, and the privacy detection in the Plus tier is a mitigation rather than a fix. For a project that needs accuracy about a user rather than about a network, a lookup table is the wrong primitive. On maintenance, the newest release is 5.3.0 from 2025-11-21 with the last push to the repository on 2026-10-21, so the tree is being worked on ahead of the last tagged release.

## Conclusion

ipinfo suits a Python application that needs IP geolocation or network ownership data and wants the vendor's own client rather than a hand-rolled HTTP wrapper, since it covers the Lite, Core and Plus tiers behind one interface and returns a Details object with dotted attributes. It is the wrong tool if you cannot hold an API token, because the library works without one only in a more limited capacity, and it is the wrong tool if you are self-hosting a self-hosted database lookup, since this is a client for a hosted service. Verify first which API tier your fields require, because the free plan is limited to 50,000 requests per month and does not include some fields such as IP type and company data, and note that the README states the package works with Python 3.5 or greater while the project metadata requires 3.10 or newer.

## FAQ

### How do I install and use the ipinfo Python library?

Install it with pip install ipinfo, then create a handler with ipinfo.getHandler(access_token) and call handler.getDetails() for your own address or handler.getDetails(ip_address) for a specific one. The Details object exposes the fields directly, for example details.city and details.loc.

### What is the difference between the Lite, Core and Plus handlers?

Each API tier has its own handler constructor: getHandlerLite, getHandlerCore and getHandlerAsyncCore for the async Core variant. The Core API provides city-level geolocation with nested geo and AS objects, and the Plus API provides enhanced data including mobile carrier info and privacy detection. All of them require authentication with your token.

### Which Python versions does the ipinfo library support?

The README says the package works with Python 3.5 or greater but only non-EOL versions are officially supported, and the project metadata requires Python 3.10 or newer. The asynchronous implementation is narrower still, supporting only Python 3.9 and 3.10 because of API changes in the asyncio library.

### Can I use the ipinfo library without a token?

Yes, but the README says it works without an authentication token only in a more limited capacity. The free plan is limited to 50,000 requests per month and does not include some fields such as IP type and company data.

### How do I get the full response as a dictionary?

Use details.all, which the README says returns all details data as a dictionary. Individual fields are also exposed directly as properties, including hostname, country, country_name, latitude, longitude, loc and postal.

## Sources

- [ipinfo/python on GitHub](https://github.com/ipinfo/python)
- [License: Apache-2.0](https://github.com/ipinfo/python/blob/master/LICENSE)
- [Project website](https://ipinfo.io)
- [README](https://github.com/ipinfo/python/blob/master/README.md)
- [Releases](https://github.com/ipinfo/python/releases)

---

Hysen Labs editorial analysis, written from the project's own repository and release notes. Cite the canonical page: https://hysenlabs.com/projects/ipinfo-python
