linetype

package module
v1.0.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Aug 5, 2026 License: Apache-2.0 Imports: 11 Imported by: 0

README

Phone Line Type Intelligence

Go Reference CI

Use Line Type Intelligence to identify the carrier and phone line type, such as mobile, landline, fixed VoIP, non-fixed VoIP, toll free, and more — with no per-lookup API cost.

Classifies +1 (US, Canada) and +52 (Mexico) numbers from published numbering-plan allocation data embedded directly in the binary.

Line Types

Type Description SMS Reachable
wireless Mobile / cellular (PCS, wireless carriers) Yes
wireline Landline (ILEC, RBOC, traditional fixed-line) No
voip VoIP and CLEC-held ranges (interconnected VoIP, fixed and non-fixed VoIP) Yes
tollfree Toll-free numbers (800, 888, 877, 866, 855, 844, 833) No
unknown No assignment on file or unmapped OCN — never a synonym for landline —

Installation

go get github.com/tomba-io/phone-line-type-intelligence

Quick Start

package main

import (
    "fmt"
    linetype "github.com/tomba-io/phone-line-type-intelligence"
)

func main() {
    n := linetype.Describe("+18168037763")

    fmt.Println(n.Class)           // wireless
    fmt.Println(n.SMSReachable)    // true
    fmt.Println(n.Carrier.Label()) // T-Mobile
    fmt.Println(n.Region.Code)     // MO
    fmt.Println(n.Region.Name)     // Missouri
    fmt.Println(n.Country)         // United States
    fmt.Println(n.International()) // +1 816-803-7763
    fmt.Println(n.National())      // (816) 803-7763
}
Direct Lookups
// Line type only (zero allocation, 11 ns)
cls := linetype.Lookup("+14155551234") // linetype.Wireless

// Carrier info (zero allocation, 17 ns)
cr := linetype.LookupCarrier("+14155551234")
fmt.Println(cr.Label()) // "AT&T"
fmt.Println(cr.OCN)     // "6006"

// Geographic region (zero allocation, 12 ns)
rg := linetype.LookupRegion("+14155551234")
fmt.Println(rg.Code, rg.Name) // "CA" "California"
Mexico
mx := linetype.Describe("+525510001234")
fmt.Println(mx.Class)   // wireless or wireline
fmt.Println(mx.Country) // Mexico
fmt.Println(mx.NPA)     // 55 (Mexico City)
CLI

A single lti binary powered by Cobra:

# Install
go install github.com/tomba-io/phone-line-type-intelligence/cmd/lti@latest

# Describe a single number
$ lti describe +18168037763
Number:        +18168037763
International: +1 816-803-7763
National:      (816) 803-7763
Line Type:     wireless
SMS Reachable: Yes
Carrier:       AT&T
OCN:           6534
Region:        Missouri
State:         MO
Country:       United States (US)

# JSON output
$ lti describe --json +18168037763

```json
{
  "block": "7",
  "carrier_brand": "AT\u0026T",
  "carrier_label": "AT\u0026T",
  "carrier_name": "NEW CINGULAR WIRELESS PCS, LLC - IL",
  "carrier_ocn": "6534",
  "country": "United States",
  "country_code": "US",
  "e164": "+18168037763",
  "international": "+1 816-803-7763",
  "line_type": "wireless",
  "national": "(816) 803-7763",
  "npa": "816",
  "nxx": "803",
  "region_code": "MO",
  "region_name": "Missouri",
  "sms_reachable": true,
  "valid": true
}

Classify a file

$ lti classify list.txt lti classify summary input lines 2377 in 1ms

wireless 1326 55.8% #####..... voip 191 8.0% .......... wireline 840 35.3% ###....... unknown 20 0.8% ..........

emitted 2377

Security audit

$ lti audit --verbose

Download source data

$ lti fetch

Build tables

$ lti build -- -co cocodes.txt -blocks blocks.txt -out data/linetype.bin

Shell completions

$ lti completion bash > /etc/bash_completion.d/lti $ lti completion zsh > "${fpath[1]}/_lti"


## Data Sources

| Country    | Source                                                             | Line Type                       | Coverage                |
| ---------- | ------------------------------------------------------------------ | ------------------------------- | ----------------------- |
| **US**     | [NANPA](https://www.nationalnanpa.com) CO codes + thousands blocks | Derived from OCN category       | 100% of assigned blocks |
| **Canada** | [CNAC](https://cnac.ca) CO codes + blocks                          | Derived from OCN category       | 100% of assigned blocks |
| **Mexico** | [IFT](https://sns.ift.org.mx) Plan Nacional de Numeracion          | Published directly (Fijo/Movil) | 100% (1B+ numbers)      |

## Embedded Tables

| Table          | Size   | Format                                          |
| -------------- | ------ | ----------------------------------------------- |
| `linetype.bin` | 4 MB   | 4-bit class per thousands-block, 8M slots, O(1) |
| `carrier.bin`  | 16 MB  | 16-bit OCN index per block, O(1)                |
| `carriers.csv` | 128 KB | OCN to name and brand mapping                   |
| `region.bin`   | 800 KB | 1 byte per NXX, state/province                  |
| `mx.bin`       | 3.4 MB | Sorted ranges, O(log n) binary search           |

## Performance

All lookups are zero-allocation. Formatting methods (`International()`,
`National()`) are computed lazily — you only pay for them when called.

| Operation           | Time   | Allocations | Notes                                 |
| ------------------- | ------ | ----------- | ------------------------------------- |
| `Lookup()`          | 11 ns  | 0           | Line type only, single array index    |
| `LookupCarrier()`   | 17 ns  | 0           | Carrier from OCN index                |
| `LookupRegion()`    | 12 ns  | 0           | State/province per NXX                |
| `Describe()`        | 45 ns  | 0           | Full result: class + carrier + region |
| `Describe()` Mexico | 97 ns  | 0           | Binary search over sorted ranges      |
| Bulk (2377 numbers) | 175 µs | 0           | 13.6 million classifications/sec      |
| Parallel (6 cores)  | 15 ns  | 0           | No contention on concurrent access    |

## Tests

```bash
go test ./... -v        # 24 tests + fuzz seeds + example tests
go test -fuzz=FuzzLookup -fuzztime=30s   # fuzz testing
Test What it verifies
TestValidate Embedded linetype.bin is exactly 4,000,000 bytes
TestCarrierAvailable Carrier table (16 MB) loaded correctly
TestRegionAvailable Region table (800 KB) loaded correctly
TestMXAvailable Mexico range table has valid MXPN magic header
TestLookupInvalid 11 invalid inputs all return Invalid class
TestLookupPrefix Out-of-range prefixes return Unknown
TestDescribeUSFormatting NPA/NXX/Block parsing, International/National format
TestDescribeInvalid Non-NANP/MX numbers return Valid=false
TestDescribeMexico 5 Mexican area codes (55, 56, 81, 33, 998)
TestMexicoInvalid Wrong-length and 0-leading MX numbers rejected
TestMexicoRangeEdges Boundary values at range start/end
TestClassString All Class values serialize correctly
TestClassMarshalText JSON marshaling matches String()
TestSMSReachable Wireless+VoIP reachable, others not
TestLookupCarrier Carrier lookup returns valid types
TestCarrierString Brand > Name > OCN > "unknown" precedence
TestCarrierLabel Brand > Name precedence
TestLookupRegion NY/New York/US for 212 numbers
TestHelpers YesNo() and Or() utility functions
TestGoldenListTxt Exact match: 1326 wireless, 191 voip, 840 wireline, 20 unknown
TestConcurrency 10 goroutines hitting all paths simultaneously
FuzzLookup Random inputs never panic (1.4M+ executions)
ExampleDescribe Verified example in go doc
ExampleLookup Verified example in go doc
ExampleLookup_invalid Verified example in go doc
ExampleClass_SMSReachable Verified example in go doc

Benchmarks

go test -bench=. -benchmem -count=3
BenchmarkLookup-6           100000000    11.4 ns/op    0 B/op   0 allocs/op
BenchmarkDescribe-6          26700000    44.7 ns/op    0 B/op   0 allocs/op
BenchmarkDescribeMexico-6    12300000    97.1 ns/op    0 B/op   0 allocs/op
BenchmarkLookupCarrier-6     70500000    17.1 ns/op    0 B/op   0 allocs/op
BenchmarkLookupRegion-6      95000000    11.6 ns/op    0 B/op   0 allocs/op
BenchmarkBulkThroughput-6        6800   175.6 µs/op    0 B/op   0 allocs/op   2377 numbers/op
BenchmarkParallel-6          80000000    15.1 ns/op    0 B/op   0 allocs/op

Building the Tables

# 1. Download source data
lti fetch
# or: bash scripts/get-data.sh

# 2. Build US + Canada tables
lti build -- -co _build/linetype/CoCodeAssignment_*.txt \
    -blocks _build/linetype/ThousandsBlockAssignment_*.txt \
    -ocn data/ocn.csv -out data/linetype.bin \
    -carrier-out data/carrier.bin -carriers-out data/carriers.csv \
    -region-out data/region.bin -regions-out data/regions.csv

# 3. Build Mexico table (independent, no OCN map needed)
lti build -- -mx _build/linetype/pnn_Publico_*.csv \
    -mx-out data/mx.bin -mx-carriers-out data/mx_carriers.csv

# 4. Re-embed
go build ./...
Geographic Blocking (.proxyrc)

reports.nanpa.com sits behind Imperva, which refuses requests from certain countries with HTTP 403. If lti fetch fails:

cp scripts/.proxyrc.example scripts/.proxyrc
# edit .proxyrc with your proxy credentials — NEVER commit this file
lti fetch

Accuracy

See ACCURACY.md for the full accuracy analysis, measurement protocol, and the distinction between assignment accuracy and porting error.

This is block assignment data, not current line type. It reports the original carrier allocation and is wrong on every ported number. unknown means no assignment is on file and is never a synonym for landline. Not a basis for TCPA or DNC claims.

License

Please see the Apache 2.0 license file for more information.

Documentation

Overview

Package linetype provides Phone Line Type Intelligence for North American and Mexican phone numbers.

Use Line Type Intelligence to identify the carrier and phone line type — mobile, landline, fixed VoIP, non-fixed VoIP, toll free, and more — with no per-lookup API cost. All data is embedded in the binary at compile time from published numbering-plan allocation data (NANPA, CNAC, IFT).

Quick start

n := linetype.Describe("+18168037763")
fmt.Println(n.Class)           // wireless
fmt.Println(n.SMSReachable)    // true
fmt.Println(n.Carrier.Label()) // T-Mobile
fmt.Println(n.Region.Name)     // Missouri

Direct lookups

cls := linetype.Lookup("+14155551234")        // zero-alloc, 12 ns
cr  := linetype.LookupCarrier("+14155551234") // carrier info
rg  := linetype.LookupRegion("+14155551234")  // geographic region

Supported countries

  • +1 United States and Canada (NANPA block-level, O(1) array lookup)
  • +52 Mexico (IFT range table, O(log n) binary search)

Scope limit

This package reflects block assignment, not current line type. It does not account for local number portability. See ACCURACY.md for error analysis.

Package linetype provides Line Type Intelligence for North American (+1) and Mexican (+52) phone numbers.

Use Line Type Intelligence to identify the carrier and phone line type, such as mobile, landline, fixed VoIP, non-fixed VoIP, toll free, and more — with no per-lookup API cost.

All data is embedded in the binary at compile time from published numbering-plan allocation data (NANPA, CNAC, IFT).

IMPORTANT SCOPE LIMIT: this package reflects *block assignment*, i.e. which carrier a number range was originally allocated to. It does not account for local number portability. See ACCURACY.md for the expected error rate.

Index

Examples

Constants

This section is empty.

Variables

View Source
var ErrBlobSize = errors.New("linetype: embedded table has unexpected size")

ErrBlobSize is returned by Validate if the embedded table is the wrong size.

Functions

func CarrierAvailable

func CarrierAvailable() bool

CarrierAvailable reports whether a carrier table was built into this binary.

func MXAvailable

func MXAvailable() bool

MXAvailable reports whether a Mexican range table was built into this binary.

func Or

func Or(s, fallback string) string

Or returns fallback when s is empty.

func RegionAvailable

func RegionAvailable() bool

RegionAvailable reports whether a region table was built into this binary.

func Validate

func Validate() error

Validate checks the embedded table at startup. Call it in main; a truncated or stale blob is a deploy error, not a per-request condition.

func YesNo

func YesNo(b bool) string

YesNo renders a bool for human-facing reports.

Types

type Carrier

type Carrier struct {
	OCN   string // operating company number, e.g. "6529"
	Name  string // company name as published, e.g. "T-MOBILE USA, INC."
	Brand string // optional human-facing name, e.g. "T-Mobile"
}

Carrier identifies the company holding a number range, as published in the assignment data. It is the *block holder*, not the current service provider.

func LookupCarrier

func LookupCarrier(e164 string) Carrier

LookupCarrier returns the company holding the range an E.164 +1 number falls in.

func LookupCarrierPrefix

func LookupCarrierPrefix(prefix uint32) Carrier

LookupCarrierPrefix is LookupCarrier for a seven-digit NPA-NXX-B prefix.

func (Carrier) Known

func (c Carrier) Known() bool

Known reports whether any carrier was on file.

func (Carrier) Label

func (c Carrier) Label() string

Label returns the brand if available, otherwise the published name.

func (Carrier) String

func (c Carrier) String() string

type Class

type Class uint8

Class is the assignment-derived line type of a number range.

const (
	// Unknown means the block is unassigned, or the holding OCN is absent from
	// the classification map. Never treat Unknown as a synonym for any other
	// class — abstain instead.
	Unknown  Class = iota
	Wireline       // landline (ILEC, RBOC, traditional fixed-line)
	Wireless       // mobile / cellular (PCS, wireless carriers)
	VoIP           // interconnected VoIP and CLEC-held ranges; frequently SMS-reachable
	TollFree       // toll-free numbers (800, 888, 877, 866, 855, 844, 833)
	Invalid        // structurally not a dialable NANP geographic number
)

func Lookup

func Lookup(e164 string) Class

Lookup returns the assignment-derived class of an E.164 +1 number. It is safe for concurrent use and performs no allocation.

Example
c := Lookup("+12025551234")
fmt.Println(c)
fmt.Println(c.SMSReachable())
Output:
unknown
false
Example (Invalid)
c := Lookup("+442071234567")
fmt.Println(c)
Output:
invalid

func LookupPrefix

func LookupPrefix(prefix uint32) Class

LookupPrefix returns the class for an already-extracted seven-digit NPA-NXX-B prefix.

func (Class) MarshalText

func (c Class) MarshalText() ([]byte, error)

MarshalText renders the class as its lowercase name for JSON serialisation.

func (Class) SMSReachable

func (c Class) SMSReachable() bool

SMSReachable reports whether the class is plausibly able to receive SMS. VoIP counts: a large share of CLEC and interconnected-VoIP ranges are SMS-enabled, and dropping them discards reachable numbers.

Example
fmt.Println(Wireless.SMSReachable())
fmt.Println(VoIP.SMSReachable())
fmt.Println(Wireline.SMSReachable())
Output:
true
true
false

func (Class) String

func (c Class) String() string

type Number

type Number struct {
	Valid        bool
	Country      string // "United States", "Canada", "Mexico"
	CountryCode  string // "US", "CA", "MX"
	E164         string // +18168037763
	NPA          string // 816
	NXX          string // 803
	Block        string // 7
	Class        Class
	SMSReachable bool
	Carrier      Carrier
	Region       Region
	// contains filtered or unexported fields
}

Number is everything this package knows about one number, assembled from the class, carrier and region tables.

func Describe

func Describe(e164 string) Number

Describe assembles everything known about an E.164 +1 or +52 number in one pass. Formatting strings (International, National) are computed lazily via methods to keep the hot path zero-allocation.

Example
n := Describe("+12025551234")
fmt.Println(n.Valid)
fmt.Println(n.NPA)
fmt.Println(n.NXX)
fmt.Println(n.International())
fmt.Println(n.National())
Output:
true
202
555
+1 202-555-1234
(202) 555-1234

func (Number) CarrierLabel

func (n Number) CarrierLabel() string

CarrierLabel is the name to show a human.

func (Number) International

func (n Number) International() string

International returns the E.164 number in international format. For +1: "+1 816-803-7763". For +52: "+52 55 1000 1234".

func (Number) National

func (n Number) National() string

National returns the number in national format. For +1: "(816) 803-7763". For +52: "55 1000 1234".

type Region

type Region struct {
	Code        string // state or province code, e.g. "MO", "ON"
	Name        string // full name, e.g. "Missouri", "Ontario"
	Country     string // e.g. "United States"
	CountryCode string // ISO 3166-1 alpha-2, e.g. "US"
}

Region is the geography a number range is assigned to.

func LookupRegion

func LookupRegion(e164 string) Region

LookupRegion returns the geography of an E.164 +1 number's NXX.

func (Region) Known

func (r Region) Known() bool

Known reports whether any region was on file.

Directories

Path Synopsis
cmd
ltbuild command
Command ltbuild constructs the packed line-type table from NANPA central office code assignment records, thousands-block pooling records, and an OCN classification map.
Command ltbuild constructs the packed line-type table from NANPA central office code assignment records, thousands-block pooling records, and an OCN classification map.
lti command
Command lti is the Phone Line Type Intelligence CLI.
Command lti is the Phone Line Type Intelligence CLI.
examples
basic command
Example: basic line type lookup for a single number.
Example: basic line type lookup for a single number.
csv-classify command
Example: read a CSV of phone numbers, classify each, and output enriched CSV.
Example: read a CSV of phone numbers, classify each, and output enriched CSV.
internal
cli

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL