Skip to main content

HLR & Operator Lookup

Query phone number information including network operator, validity, portability status, and pricing before sending SMS messages.

What is HLR?

HLR (Home Location Register) is a database that contains information about mobile phone subscribers on a network. HLR lookup allows you to:

  • ✅ Verify if a phone number is valid and active
  • ✅ Identify the mobile network operator
  • ✅ Check if a number has been ported to another operator
  • ✅ Get pricing information for sending to that number
  • ✅ Clean your recipient lists before campaigns

HLR Request

Perform HLR lookup for one or multiple phone numbers.

Endpoint:

GET https://www.lightsms.com/external/get/hlr.php

Required Parameters:

ParameterTypeDescription
loginstringYour LightSMS login
signaturestringMD5 signature
phonestringPhone number(s) - comma-separated (max 100)
timestampintegerUTC timestamp (valid for 10 seconds)

Optional Parameters:

ParameterTypeDescription
returnstringResponse format: json or xml

Example Requests

Single Number Lookup

curl "https://www.lightsms.com/external/get/hlr.php?login=YourLogin&phone=37061234567&signature=generated_signature&timestamp=1732809600&return=json"

Multiple Numbers Lookup

curl "https://www.lightsms.com/external/get/hlr.php?login=YourLogin&phone=37061234567,37062345678,37063456789&signature=generated_signature&timestamp=1732809600&return=json"

Operator Lookup

Get detailed information about a phone number's network operator and pricing.

Endpoint:

GET https://www.lightsms.com/external/get/operator.php

Required Parameters:

ParameterTypeDescription
loginstringYour LightSMS login
signaturestringMD5 signature
phonestringPhone number to query
timestampintegerUTC timestamp (valid for 10 seconds)

Optional Parameters:

ParameterTypeDescription
returnstringResponse format: json or xml
textstringSMS text (for accurate pricing based on message length)

Operator Lookup Response

Example Request:

curl "https://www.lightsms.com/external/get/operator.php?login=YourLogin&signature=generated_signature&timestamp=1732809600&return=json&phone=37061234567"

Response (JSON):

{
"currency": "EUR",
"error": 0,
"mcc": "246",
"mnc": "02",
"ok": true,
"operator": "Tele2 Lithuania",
"phone": "37061234567",
"ported": 0,
"price": 0.012,
"regionCode": 0,
"timeZone": 2
}

Response Fields

FieldTypeDescription
currencystringCurrency code (EUR, USD, etc.)
errorintegerError code (0 = success)
mccstringMobile Country Code
mncstringMobile Network Code
okbooleantrue if lookup successful
operatorstringNetwork operator name
phonestringQueried phone number
portedinteger1 if number was ported, 0 if not
pricefloatCost to send SMS to this number
regionCodeintegerRegion/area code
timeZoneintegerTimezone offset from UTC

Code Examples

PHP - Operator Lookup

<?php
function getOperatorInfo($login, $apiKey, $phone) {
// Get timestamp
$timestamp = trim(file_get_contents('https://www.lightsms.com/external/get/timestamp.php'));

// Prepare parameters
$params = [
'login' => $login,
'phone' => $phone,
'timestamp' => $timestamp,
'return' => 'json'
];

// Create signature
ksort($params);
$signature = md5(implode($params) . $apiKey);
$params['signature'] = $signature;

// Make request
$url = 'https://www.lightsms.com/external/get/operator.php?' . http_build_query($params);
$response = file_get_contents($url);

return json_decode($response, true);
}

// Configuration
$login = 'YourLogin';
$apiKey = 'your_api_key_here';
$phone = '37061234567';

// Get operator info
$info = getOperatorInfo($login, $apiKey, $phone);

if ($info['ok']) {
echo "Phone: {$info['phone']}\n";
echo "Operator: {$info['operator']}\n";
echo "Price: {$info['price']} {$info['currency']}\n";
echo "Ported: " . ($info['ported'] ? 'Yes' : 'No') . "\n";
echo "Timezone: UTC{$info['timeZone']:+d}\n";
} else {
echo "Error code: {$info['error']}\n";
}
?>

Python - Validate Numbers Before Sending

import requests
import hashlib
from urllib.parse import urlencode

def get_operator_info(login, api_key, phone):
# Get timestamp
timestamp_response = requests.get('https://www.lightsms.com/external/get/timestamp.php')
timestamp = timestamp_response.text.strip()

# Prepare parameters
params = {
'login': login,
'phone': phone,
'timestamp': timestamp,
'return': 'json'
}

# Create signature
sorted_params = sorted(params.items())
param_string = ''.join([str(value) for key, value in sorted_params])
signature = hashlib.md5((param_string + api_key).encode()).hexdigest()
params['signature'] = signature

# Make request
url = f'https://www.lightsms.com/external/get/operator.php?{urlencode(params)}'
response = requests.get(url)

return response.json()

def validate_and_send(login, api_key, phone, message):
"""Validate phone number before sending SMS."""
# Check operator info
info = get_operator_info(login, api_key, phone)

if not info['ok']:
print(f"❌ Invalid phone number: {phone}")
return False

# Log operator details
print(f"✅ Valid number: {phone}")
print(f" Operator: {info['operator']}")
print(f" Price: {info['price']} {info['currency']}")

if info['ported']:
print(f" ⚠️ Number has been ported")

# Calculate cost estimate
message_parts = len(message) // 160 + 1
estimated_cost = info['price'] * message_parts
print(f" Estimated cost: {estimated_cost:.4f} {info['currency']}")

# Proceed with sending
return True

# Configuration
LOGIN = 'YourLogin'
API_KEY = 'your_api_key_here'

# Validate before sending
phone = '37061234567'
message = 'Hello from LightSMS!'

if validate_and_send(LOGIN, API_KEY, phone, message):
# Send SMS
print("Proceeding with SMS sending...")

JavaScript - Bulk Number Validation

const crypto = require('crypto');
const axios = require('axios');

async function getOperatorInfo(login, apiKey, phone) {
// Get timestamp
const timestampResponse = await axios.get('https://www.lightsms.com/external/get/timestamp.php');
const timestamp = timestampResponse.data.trim();

// Prepare parameters
const params = {
login: login,
phone: phone,
timestamp: timestamp,
return: 'json'
};

// Create signature
const sortedKeys = Object.keys(params).sort();
const paramString = sortedKeys.map(key => params[key]).join('');
const signature = crypto.createHash('md5').update(paramString + apiKey).digest('hex');
params.signature = signature;

// Make request
const queryString = new URLSearchParams(params).toString();
const url = `https://www.lightsms.com/external/get/operator.php?${queryString}`;
const response = await axios.get(url);

return response.data;
}

async function validatePhoneList(login, apiKey, phoneNumbers) {
const results = {
valid: [],
invalid: [],
ported: [],
totalCost: 0
};

for (const phone of phoneNumbers) {
try {
const info = await getOperatorInfo(login, apiKey, phone);

if (info.ok) {
results.valid.push({
phone: phone,
operator: info.operator,
price: info.price
});

if (info.ported) {
results.ported.push(phone);
}

results.totalCost += info.price;
} else {
results.invalid.push(phone);
}

// Rate limiting - wait 100ms between requests
await new Promise(resolve => setTimeout(resolve, 100));

} catch (error) {
console.error(`Error validating ${phone}:`, error.message);
results.invalid.push(phone);
}
}

return results;
}

// Configuration
const LOGIN = 'YourLogin';
const API_KEY = 'your_api_key_here';

// Validate list of numbers
const phoneNumbers = [
'37061234567',
'37062345678',
'37063456789'
];

(async () => {
console.log('Validating phone numbers...\n');

const results = await validatePhoneList(LOGIN, API_KEY, phoneNumbers);

console.log(`✅ Valid numbers: ${results.valid.length}`);
console.log(`❌ Invalid numbers: ${results.invalid.length}`);
console.log(`⚠️ Ported numbers: ${results.ported.length}`);
console.log(`💰 Estimated total cost: ${results.totalCost.toFixed(4)} EUR\n`);

console.log('Valid numbers:');
results.valid.forEach(item => {
console.log(` - ${item.phone} (${item.operator}) - ${item.price} EUR`);
});

if (results.invalid.length > 0) {
console.log('\nInvalid numbers:');
results.invalid.forEach(phone => console.log(` - ${phone}`));
}
})();

HLR Statistics

Get statistics about HLR requests for a specific date range.

Endpoint:

GET https://www.lightsms.com/external/get/hlr_stat.php

Required Parameters:

ParameterTypeDescription
loginstringYour LightSMS login
signaturestringMD5 signature
fromstringStart date (format: YYYY-MM-DD)
tostringEnd date (format: YYYY-MM-DD)
timestampintegerUTC timestamp

Optional Parameters:

ParameterTypeDescription
returnstringResponse format: json or xml

HLR Statistics Example

curl "https://www.lightsms.com/external/get/hlr_stat.php?login=YourLogin&from=2025-01-01&to=2025-01-31&signature=generated_signature&timestamp=1732809600&return=json"

Use Cases

1. List Cleaning

Remove invalid numbers before sending campaigns:

function cleanPhoneList($login, $apiKey, $phoneList) {
$validNumbers = [];
$invalidNumbers = [];

foreach ($phoneList as $phone) {
$info = getOperatorInfo($login, $apiKey, $phone);

if ($info['ok']) {
$validNumbers[] = $phone;
} else {
$invalidNumbers[] = $phone;
}

// Rate limiting
usleep(100000); // 100ms delay
}

echo "Valid: " . count($validNumbers) . "\n";
echo "Invalid: " . count($invalidNumbers) . "\n";

return $validNumbers;
}

2. Cost Estimation

Calculate campaign costs before sending:

def estimate_campaign_cost(login, api_key, phone_list, message_length):
total_cost = 0
message_parts = (message_length // 160) + 1

for phone in phone_list:
info = get_operator_info(login, api_key, phone)
if info['ok']:
total_cost += info['price'] * message_parts

return total_cost

# Example
phones = ['37061234567', '37062345678', '37063456789']
message_length = 150 # characters

cost = estimate_campaign_cost(LOGIN, API_KEY, phones, message_length)
print(f"Campaign estimated cost: {cost:.2f} EUR")

3. Operator-Based Segmentation

Group recipients by operator for targeted campaigns:

async function segmentByOperator(login, apiKey, phoneList) {
const segments = {};

for (const phone of phoneList) {
const info = await getOperatorInfo(login, apiKey, phone);

if (info.ok) {
const operator = info.operator;

if (!segments[operator]) {
segments[operator] = [];
}

segments[operator].push(phone);
}

await new Promise(resolve => setTimeout(resolve, 100));
}

return segments;
}

// Send different messages to different operators
const segments = await segmentByOperator(LOGIN, API_KEY, phoneList);

for (const [operator, phones] of Object.entries(segments)) {
console.log(`${operator}: ${phones.length} recipients`);
// Send targeted message to this operator's customers
}

Pricing Information

Get pricing for all available network operators.

Endpoint:

GET https://www.lightsms.com/external/get/prices.php

Required Parameters:

ParameterTypeDescription
loginstringYour LightSMS login
signaturestringMD5 signature
timestampintegerUTC timestamp

Pricing Response Example

curl "https://www.lightsms.com/external/get/prices.php?login=YourLogin&signature=generated_signature&timestamp=1732809600"

Response (JSON):

{
"24602": {
"NETWORK_NAME": "Tele2 Lithuania",
"COUNTRY": "Lithuania",
"PRICE": "0.012",
"CURRENCY": "EUR"
},
"24601": {
"NETWORK_NAME": "Omnitel (Telia)",
"COUNTRY": "Lithuania",
"PRICE": "0.012",
"CURRENCY": "EUR"
},
"24603": {
"NETWORK_NAME": "Bite Lithuania",
"COUNTRY": "Lithuania",
"PRICE": "0.012",
"CURRENCY": "EUR"
}
}

Common Errors

Error 36: Cannot Obtain Information About Phone

Problem: HLR lookup failed for the phone number

Possible causes:

  • Invalid phone number format
  • Number doesn't exist
  • Network temporarily unavailable

Solutions:

  • ✅ Verify phone number format (international format)
  • ✅ Retry after a short delay
  • ✅ Contact support if persistent

Next Steps


Need Help?

For questions about HLR and operator lookup: