linetype

package module
v1.0.1 Latest Latest
Warning

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

Go to latest
Published: Aug 20, 2026 License: Apache-2.0 Imports: 10 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 stored as Protocol Buffers.

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()) // AT&T
    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, 12 ns)
cls := linetype.Lookup("+14155551234") // linetype.Wireless

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

// Geographic region (zero allocation, 13 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
{
  "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 -proto-out data/phone_data.pb

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

Coverage

+1 (US and Canada) — complete
Assigned blocks Classified Coverage
United States 1,980,190 1,980,190 100.00%
Canada 286,668 286,668 100.00%
Total 2,267,088 2,267,088 100.00%

All 3,117 OCNs holding blocks are classified.

Class distribution:

US Canada
wireless 37.0% 29.5%
voip 36.8% 44.3%
wireline 26.2% 26.2%
+52 (Mexico) — complete
Numbers Share
Mobile (CPP + MPP) 876,678,000 85.8%
Fixed (FIJO) 145,582,662 14.2%
Total classified 1,022,260,662 100%

Data Sources

Country Source Line Type Coverage
US NANPA CO codes + thousands blocks Derived from OCN category 100% of assigned blocks
Canada CNAC CO codes + blocks Derived from OCN category 100% of assigned blocks
Mexico IFT Plan Nacional de Numeracion Published directly (Fijo/Movil) 100% (1B+ numbers)

Data Format (Protocol Buffers)

All lookup data is stored in a single data/phone_data.pb file (~16 MB), loaded at runtime from disk. The proto definition is at proto/linetype/v1/linetype.proto.

Table Format
ClassTable 4 MB nibble-packed bytes, 4-bit class per block, O(1) lookup
CarrierTable NXX base bytes + sparse exceptions + carrier directory, O(log n)
RegionTable 800 KB byte index per NXX + region directory, O(1) lookup
MXTable Sorted ranges + 3-digit prefix index + carrier directory, O(log n)

Data path resolution: SetDataPath() > LINETYPE_DATA_PATH env > <exe_dir>/data/phone_data.pb > ./data/phone_data.pb

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() 12 ns 0 Line type only, single array index
LookupCarrier() 51 ns 0 NXX base + exception search
LookupRegion() 13 ns 0 State/province per NXX
Describe() 84 ns 0 Full result: class + carrier + region
Describe() Mexico 62 ns 0 Binary search with 3-digit prefix index
Bulk (2377 numbers) 543 us 0 4.4 million classifications/sec
Parallel (6 cores) 15 ns 0 No contention on concurrent access

Tests

go test ./... -v        # 22 tests + fuzz seeds + example tests
go test -fuzz=FuzzLookup -fuzztime=30s   # fuzz testing
Test What it verifies
TestValidate Class table is exactly 4,000,000 bytes
TestCarrierAvailable Carrier table loaded correctly
TestRegionAvailable Region table (800 KB) loaded correctly
TestMXAvailable Mexico range table loaded correctly
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 (6.7M+ 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    12.1 ns/op    0 B/op   0 allocs/op
BenchmarkDescribe-6          14000000    84.3 ns/op    0 B/op   0 allocs/op
BenchmarkDescribeMexico-6    19200000    62.4 ns/op    0 B/op   0 allocs/op
BenchmarkLookupCarrier-6     23000000    51.5 ns/op    0 B/op   0 allocs/op
BenchmarkLookupRegion-6      91000000    13.1 ns/op    0 B/op   0 allocs/op
BenchmarkBulkThroughput-6        2130   543.6 us/op    0 B/op   0 allocs/op   2377 numbers/op
BenchmarkParallel-6          80000000    15.0 ns/op    0 B/op   0 allocs/op

Building the Tables

# Using make (recommended)
make data-fetch     # download NANPA, CNAC, IFT source data
make data-build     # build all tables (US, CA, MX)
make test           # verify
make audit          # integrity check

# Or manually
lti fetch
lti build -- -co _build/linetype/CoCodeAssignment_*.txt \
    -blocks _build/linetype/ThousandsBlockAssignment_*.txt \
    -ocn data/ocn.csv \
    -mx _build/linetype/pnn_Publico_*.csv \
    -mx-brands data/mx_brands.csv \
    -proto-out data/phone_data.pb
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. Data is loaded at runtime from a Protocol Buffers file built from published numbering-plan allocation data (NANPA, CNAC, IFT).

Quick start

linetype.SetDataPath("data/phone_data.pb") // optional; auto-resolved
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")        // class only
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.

Data is loaded at runtime from a Protocol Buffers file built 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: class table has unexpected size")

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

Functions

func CarrierAvailable

func CarrierAvailable() bool

CarrierAvailable reports whether a carrier table was loaded.

func LoadData added in v1.0.1

func LoadData() error

LoadData explicitly loads and parses the protobuf data file. It is safe to call from multiple goroutines; the first call does the work.

func MXAvailable

func MXAvailable() bool

MXAvailable reports whether a Mexican range table was loaded.

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 loaded.

func SetDataPath added in v1.0.1

func SetDataPath(path string)

SetDataPath configures the path to phone_data.pb. Must be called before any Lookup function. If not called, the path is resolved from LINETYPE_DATA_PATH env var or defaults to data/phone_data.pb relative to the executable.

func Validate

func Validate() error

Validate checks the class table. Call it in main; a truncated or stale table 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.

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
proto

Jump to

Keyboard shortcuts

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