Telnyx

Look Up Phone Number Carrier and Line Type with Python

By Harpreet Singh Seehra

A phone number carrier lookup identifies the current network operator, line type, number type, and portability status tied to a phone number. Developers use it to decide whether a number can receive SMS, whether a call should route to an agent, and whether contact data is current before the first message or call goes out.

The Telnyx Number Lookup API returns carrier, line type, and portability data for any phone number in a single request, using Telnyx carrier network data rather than only a third-party reseller feed. This walkthrough builds a Python Flask service that wraps that API with a 24-hour in-memory cache so repeat lookups are fast and do not create repeat API calls during the TTL.

The full code is available in the Telnyx code examples repo: phone-number-lookup-python.

Build a phone number carrier lookup with Python

The Flask app exposes three endpoints:

MethodPathPurpose
POST/lookupLook up a number from a JSON body
GET/lookup/<phone_number>Look up a number from the URL path
GET/cache/statsInspect the in-memory cache

When a lookup request arrives, the app checks the cache first. On a cache miss, it calls the Telnyx Number Lookup API, extracts carrier name, carrier type, line type, number type, and portability status, then returns a clean JSON response. Cached responses include from_cache set to true.

Products used

Number Lookup is a single API call: GET /v2/number_lookup/{phone_number}. There are no webhooks, no long-running jobs, and no polling. For endpoint details, see the Number Lookup guide.

Note: Send phone numbers in E.164 format, such as +15551234567. The example rejects numbers that do not start with +.

Why phone number lookup matters

Number lookup is not a standalone task. It is a building block for routing, trust, deliverability, and lead quality.

Screen inbound calls

Check carrier and line type before connecting a caller to an agent. If you route calls with Telnyx Voice API, lookup results can feed programmable call routing before a caller reaches a queue.

Enrich leads

Sales teams can tell whether a prospect has a mobile line, landline, or disposable VoIP number. Teams that manage inventory through Telnyx Phone Numbers can search, buy, and manage numbers in one place.

Route messages

Landlines usually cannot receive SMS. With Telnyx SMS API, lookup results can keep text workflows focused on mobile-capable numbers.

Detect porting

A number that was recently ported may point to a carrier change. That matters for compliance checks, deliverability, and customer data freshness.

Free lookup tools compared with carrier lookup APIs

Free web tools are useful for one-off checks, but they usually require manual input and do not fit automated call routing, lead enrichment, or fraud screening. An API approach works inside your application, where lookup results can be cached, logged, monitored, and used in routing decisions.

Free lookup toolsTelnyx Number Lookup APITwilio Lookup
Data source: Often public or reseller data shown on a manual web page.Data source: Telnyx carrier network data returned through API fields.Data source: Provider lookup data returned through Twilio endpoints.
API access: Usually limited or unavailable.API access: Yes, with carrier, line type, number type, and portability fields.API access: Yes, through Twilio Lookup.
Cache support: Manual tools do not manage your app cache.Cache support: Add app-side cache logic, as shown in this Flask example.Cache support: Add app-side cache logic based on your workflow.
Integration: Best for a single manual check.Integration: Best for Python services, routing systems, lead enrichment, and fraud checks.Integration: Best for teams already building around Twilio.

Lookup pipeline

This example uses a simple request, cache, API, response pattern. A cache hit returns local JSON. A cache miss calls Telnyx, stores the result for 24 hours, and returns the same response shape to the client.

flow
Telnyx Number Lookup pipeline

[Client request] | v [Flask /lookup endpoint] | v [Cache check] | hit | miss v v [Return cached JSON] [Telnyx Number Lookup API] | v [Store in 24h cache] | v [Return JSON response]

Prerequisites

  • Python 3.8 or later
  • A Telnyx account with a funded balance
  • A Telnyx API key from the Telnyx Portal
  • curl or Postman to test the endpoints

Set up the Flask service

bash
git clone https://github.com/team-telnyx/telnyx-code-examples.git
cd telnyx-code-examples/phone-number-lookup-python
cp .env.example .env
pip install -r requirements.txt

Edit .env and set your API key:

env
TELNYX_API_KEY=KEY012...CDEF
FLASK_DEBUG=false

Start the server:

bash
python app.py

The app runs on http://localhost:5000.

How the code works

Client initialization

The Telnyx Python SDK creates an authenticated client once at startup:

python
client = telnyx.Telnyx(api_key=os.getenv("TELNYX_API_KEY"))

The lookup function

The core function validates the phone number format, checks the cache, and calls Telnyx on a miss.

python
def lookup_phone_number(phone_number: str) -> dict:
    if not phone_number.startswith("+"):
        raise ValueError("Phone number must be in E.164 format (e.g., +15551234567)")
cached_result = get_cached_lookup(phone_number)
if cached_result:
    cached_result["from_cache"] = True
    return cached_result

response = client.number_lookup.retrieve(phone_number)

lookup_data = {
    "phone_number": response.data.phone_number,
    "country_code": response.data.country_code,
    "carrier": {
        "name": response.data.carrier.name if response.data.carrier else None,
        "type": response.data.carrier.type if response.data.carrier else None,
    },
    "line_type": response.data.line_type,
    "number_type": response.data.number_type,
    "portability": {
        "status": response.data.portability.status if response.data.portability else None,
        "last_checked_at": response.data.portability.last_checked_at if response.data.portability else None,
    },
    "from_cache": False,
}

cache_lookup_result(phone_number, lookup_data)
return lookup_data</code></pre>

Caching

The cache is a Python dict with a 24-hour TTL. Each entry stores the lookup result and a timestamp. is_cache_valid() compares the stored timestamp against the TTL, and expired entries are replaced on the next lookup.

This keeps repeated lookups of the same number free of repeat API calls during the 24-hour window.

Error handling

The Flask endpoints catch Telnyx SDK exceptions and return clear HTTP status codes:

  • 401 for invalid API keys
  • 429 for rate limit hits
  • 503 for network errors
  • 400 for malformed requests

Test the endpoints

bash
# Look up a number with POST
curl -X POST http://localhost:5000/lookup \
  -H "Content-Type: application/json" \
  -d '{"phone_number": "+15551234567"}'

Look up a number with GET

curl http://localhost:5000/lookup/+15551234567

Check the cache

curl http://localhost:5000/cache/stats

Run the same lookup twice. The second response returns from_cache set to true.

Going to production

This example uses an in-memory cache for simplicity. For production, adapt the service around your traffic patterns and data retention needs.

  • Shared cache: Replace the in-memory dict with Redis so cached data survives restarts and is shared across instances.
  • Authentication: Add API key validation on your endpoints so the lookup service is not open to the internet.
  • Rate limiting: Protect your endpoints and stay within Telnyx Number Lookup limits.
  • Persistence: Store lookup history in a database if you need an audit trail.
  • Monitoring: Add structured logging and alert on error rates.
  • Call routing: If you connect existing PBX traffic through Telnyx SIP Trunking, lookup results can feed pre-call routing rules before traffic reaches your queue.

Resources

Related examples

  • number-lookup-fraud-screener-python for screening inbound numbers before connecting
  • number-lookup-lead-enrichment-python for enriching sales leads with carrier and CNAM data
  • cnam-caller-id-lookup-enrichment-python for caller ID enrichment
  • bulk-number-validation-cleaner-python for validating and cleaning lists of numbers

Phone number carrier lookup FAQ

How do I look up a phone number's carrier?
Use a carrier lookup service or API. For a programmatic lookup, send the phone number in E.164 format to a lookup endpoint, then read the carrier name, carrier type, line type, and portability fields from the response.
Is phone number carrier lookup free?
Some websites offer free one-off lookups, but API-based carrier lookup is usually priced per request. A cache, like the 24-hour cache in this example, helps reduce repeat lookups for the same number.
What is a carrier lookup API?
A carrier lookup API is an HTTP endpoint that accepts a phone number and returns telecom metadata, such as carrier, line type, number type, and portability. Developers use it inside routing, validation, lead enrichment, and fraud workflows.
Can I check if a phone number is a landline or mobile?
Yes. Look at the line type or number type fields in the lookup response. This is useful before sending SMS, since mobile numbers can receive text messages while many landlines cannot.
How accurate is phone number carrier data?
Accuracy depends on the data source and how recently the number was checked. Porting can change the current carrier, so APIs that include portability data and refresh through carrier-network sources are better suited to automated workflows than manual lookup pages.

Start looking up carrier dataBuild carrier, line type, and portability checks into your app with Telnyx. Review the API reference, then send your first lookup request.

Start with Number Lookup
Share on Social

Sign up for emails of our latest articles and news