The LINE check tells you whether phone numbers have a LINE account. LINE is the everyday messenger in Japan, Taiwan and Thailand, so the check matters most for customers there. It runs in bulk jobs, answers registered: true, false or null (unknown) per number, and returns no LINE ID, name or photo.
What does the LINE check tell you?
It answers whether a LINE account is associated with the number. LINE launched in Japan in 2011 and is now run by LY Corporation, which was formed in 2023 by merging LINE with Yahoo Japan's operator. Accounts are usually registered with a phone number, confirmed by a code. Contacts connect by phone number, by LINE ID, by QR code or through friend lists.
registered: true: a LINE account is associated with the number.registered: false: a conclusive answer that none is.registered: null: no conclusive answer; not charged.
Because LINE also lets people connect through IDs and QR codes, some accounts are not easy to find by number. A false means "not reachable through this number". It does not prove the person has no LINE account.
Who uses it, and why?
LINE is more than a messenger in its core markets. It is also where people follow brands, get coupons and receive service notices, and businesses reach their followers through official accounts.
- Channel planning for Japanese, Taiwanese and Thai customers. Companies expanding into these markets check which opted-in customers are on LINE before investing in an official account, instead of assuming WhatsApp coverage. See channel selection.
- Customer-contact hygiene. A regional contact list can be batch-checked to see which numbers still show messenger activity. Numbers without LINE, WhatsApp or Telegram may need re-verification.
- Sign-up screening in LINE markets. For a Japanese or Thai mobile number, the absence of a LINE account is unusual enough to feed into fraud scoring. It is not proof of fraud. Combine it with a carrier lookup.
What do you get back?
Each job row carries checks["line.registered"]; the service has no extra attributes.
| Field | Type | Meaning |
|---|---|---|
registered | boolean or null | true account found, false none found, null unknown |
status | enum | completed, pending, unknown, unsupported_country or failed |
confidence / confidence_score | enum / 0–1 | How sure the answer is |
checked_at | timestamp | When the answer was obtained |
cached / age_seconds / billed | boolean / integer / boolean | Cache and billing details |
reason | string or null | Why the answer is not conclusive |
How is it billed?
Per number, for conclusive answers only, at the bulk price. You're not charged for inconclusive results (unknown, unsupported country, timeout, invalid, duplicate). Run POST /v1/jobs/estimate for a free maximum-cost preview, and set max_cost to cap the job. See pricing.
Numbers your account checked recently can be answered from its cache free of charge. max_age: 0 forces fresh, billed checks.
What are the limits?
LINE runs in bulk jobs only. POST /v1/lookup refuses it with 403 service_disabled ("The check 'line.registered' is available in bulk jobs only (POST /v1/jobs).").
- Up to 50,000 numbers and e-mails per job, 20 checks per request, 100,000 number × check pairs per job.
- Numbers from every country are accepted. Japanese numbers written in national format (starting with 0) need
default_country: "JP". - Requests that look like sequential number ranges or generated e-mail lists are rejected.
- A daily number cap applies per account. Follow progress with
GET /v1/jobs/{id}?wait=30or a webhook.
How do I use it responsibly?
Check numbers of customers who gave them to you and agreed to be contacted. In LINE markets, people expect businesses to reach them through official accounts they chose to follow, not through unsolicited messages. Our acceptable use policy forbids unsolicited bulk messaging, building profiles of people and scanning number ranges. Japan and Thailand have their own data protection laws. Make sure you have a lawful basis for each list you check. People can object via the opt-out form.
Example request
Test jobs complete at once. +447700900001 answers registered, …002 not registered and …003 unknown. See test mode.
curl https://api.mobilevalidate.com/v1/jobs \
-H "Authorization: Bearer mv_test_publicSandboxn9ZgneuhR1B9CRfKG3fulym" \
-H "Content-Type: application/json" \
-d '{"numbers":["+447700900001","+447700900002","+447700900003"],"checks":["line"]}'// npm install mobilevalidate · Node.js 20+ · save as check.mjs and run: node check.mjs
import { MobileValidate } from "mobilevalidate";
// Omit apiKey to read MOBILEVALIDATE_API_KEY from the environment.
const mv = new MobileValidate({ apiKey: "mv_test_publicSandboxn9ZgneuhR1B9CRfKG3fulym" });
const { data, error } = await mv.jobs.create({
numbers: ["+447700900001", "+447700900002", "+447700900003"],
checks: ["line"],
});
if (error) console.error(error.code, error.message);
else console.dir(data, { depth: null });// Node.js 18+, Deno, Bun or the browser console (ES module: save as .mjs or use "type": "module").
const res = await fetch("https://api.mobilevalidate.com/v1/jobs", {
method: "POST",
headers: {
Authorization: "Bearer mv_test_publicSandboxn9ZgneuhR1B9CRfKG3fulym",
"Content-Type": "application/json",
},
body: JSON.stringify({
numbers: ["+447700900001", "+447700900002", "+447700900003"],
checks: ["line"],
}),
});
console.log(res.status, res.headers.get("x-request-id"));
console.dir(await res.json(), { depth: null });# pip install mobilevalidate-sdk
from mobilevalidate import MobileValidate
# Omit api_key to read MOBILEVALIDATE_API_KEY from the environment.
mv = MobileValidate(api_key="mv_test_publicSandboxn9ZgneuhR1B9CRfKG3fulym")
result = mv.jobs.create(
numbers=["+447700900001", "+447700900002", "+447700900003"],
checks=["line"],
)
print(result)<?php
$ch = curl_init('https://api.mobilevalidate.com/v1/jobs');
curl_setopt_array($ch, [
CURLOPT_POST => true,
CURLOPT_RETURNTRANSFER => true,
CURLOPT_HTTPHEADER => [
'Authorization: Bearer mv_test_publicSandboxn9ZgneuhR1B9CRfKG3fulym',
'Content-Type: application/json',
],
CURLOPT_POSTFIELDS => json_encode([
'numbers' => ['+447700900001', '+447700900002', '+447700900003'],
'checks' => ['line'],
]),
]);
$response = curl_exec($ch);
echo curl_getinfo($ch, CURLINFO_RESPONSE_CODE), PHP_EOL, $response, PHP_EOL;package main
import (
"fmt"
"io"
"net/http"
"strings"
)
func main() {
body := strings.NewReader(`{"numbers":["+447700900001","+447700900002","+447700900003"],"checks":["line"]}`)
req, err := http.NewRequest("POST", "https://api.mobilevalidate.com/v1/jobs", body)
if err != nil {
panic(err)
}
req.Header.Set("Authorization", "Bearer mv_test_publicSandboxn9ZgneuhR1B9CRfKG3fulym")
req.Header.Set("Content-Type", "application/json")
res, err := http.DefaultClient.Do(req)
if err != nil {
panic(err)
}
defer res.Body.Close()
out, _ := io.ReadAll(res.Body)
fmt.Println(res.Status, string(out))
}require "net/http"
require "json"
uri = URI("https://api.mobilevalidate.com/v1/jobs")
req = Net::HTTP::Post.new(uri)
req["Authorization"] = "Bearer mv_test_publicSandboxn9ZgneuhR1B9CRfKG3fulym"
req["Content-Type"] = "application/json"
req.body = JSON.generate({
"numbers" => ["+447700900001", "+447700900002", "+447700900003"],
"checks" => ["line"]
})
res = Net::HTTP.start(uri.host, uri.port, use_ssl: true) { |http| http.request(req) }
puts res.code, res.bodyRuns as pasted with the public sandbox key, which answers the test values only. In the SDKs, omit the key to use MOBILEVALIDATE_API_KEY.
Job (excerpt, test mode):
{
"object": "job",
"id": "job_0VWF4kHhV5Pc5QNT3EAJ",
"status": "completed",
"livemode": false,
"checks": [
"line.registered"
],
"created_at": "2026-09-25T14:25:30.001Z",
"completed_at": "2026-09-25T14:25:30.005Z",
"progress": {
"total": 3,
"checks_total": 3,
"done": 3,
"conclusive": 2,
"non_billable": 3
},
"retention_days": 30
}First row from GET /v1/jobs/{id}/results (test mode):
{
"kind": "phone",
"input": "+44770*****01",
"e164": "+447700900001",
"country": "GB",
"number_status": "valid",
"checks": {
"line.registered": {
"service": "line.registered",
"status": "completed",
"registered": true,
"attributes": null,
"confidence": "high",
"confidence_score": 0.99,
"checked_at": "2026-09-25T14:25:30.005Z",
"cached": false,
"age_seconds": 0,
"billed": false,
"reason": null,
"poll_after_ms": null
}
},
"test": true
}Try it now
Bulk-only service: create a job via POST /v1/jobs, then read GET /v1/jobs/{id}/results. Every example runs as pasted: it uses the public sandbox key, which answers the test values for free. In the SDKs, omit the key to use MOBILEVALIDATE_API_KEY.
curl https://api.mobilevalidate.com/v1/jobs \
-H "Authorization: Bearer mv_test_publicSandboxn9ZgneuhR1B9CRfKG3fulym" \
-H "Content-Type: application/json" \
-d '{"numbers":["+447700900001"],"checks":["line.registered"]}'// npm install mobilevalidate · Node.js 20+ · save as check.mjs and run: node check.mjs
import { MobileValidate } from "mobilevalidate";
// Omit apiKey to read MOBILEVALIDATE_API_KEY from the environment.
const mv = new MobileValidate({ apiKey: "mv_test_publicSandboxn9ZgneuhR1B9CRfKG3fulym" });
const { data, error } = await mv.jobs.create({
numbers: ["+447700900001"],
checks: ["line.registered"],
});
if (error) console.error(error.code, error.message);
else console.dir(data, { depth: null });// Node.js 18+, Deno, Bun or the browser console (ES module: save as .mjs or use "type": "module").
const res = await fetch("https://api.mobilevalidate.com/v1/jobs", {
method: "POST",
headers: {
Authorization: "Bearer mv_test_publicSandboxn9ZgneuhR1B9CRfKG3fulym",
"Content-Type": "application/json",
},
body: JSON.stringify({
numbers: ["+447700900001"],
checks: ["line.registered"],
}),
});
console.log(res.status, res.headers.get("x-request-id"));
console.dir(await res.json(), { depth: null });# pip install mobilevalidate-sdk
from mobilevalidate import MobileValidate
# Omit api_key to read MOBILEVALIDATE_API_KEY from the environment.
mv = MobileValidate(api_key="mv_test_publicSandboxn9ZgneuhR1B9CRfKG3fulym")
result = mv.jobs.create(numbers=["+447700900001"], checks=["line.registered"])
print(result)<?php
$ch = curl_init('https://api.mobilevalidate.com/v1/jobs');
curl_setopt_array($ch, [
CURLOPT_POST => true,
CURLOPT_RETURNTRANSFER => true,
CURLOPT_HTTPHEADER => [
'Authorization: Bearer mv_test_publicSandboxn9ZgneuhR1B9CRfKG3fulym',
'Content-Type: application/json',
],
CURLOPT_POSTFIELDS => json_encode([
'numbers' => ['+447700900001'],
'checks' => ['line.registered'],
]),
]);
$response = curl_exec($ch);
echo curl_getinfo($ch, CURLINFO_RESPONSE_CODE), PHP_EOL, $response, PHP_EOL;package main
import (
"fmt"
"io"
"net/http"
"strings"
)
func main() {
body := strings.NewReader(`{"numbers":["+447700900001"],"checks":["line.registered"]}`)
req, err := http.NewRequest("POST", "https://api.mobilevalidate.com/v1/jobs", body)
if err != nil {
panic(err)
}
req.Header.Set("Authorization", "Bearer mv_test_publicSandboxn9ZgneuhR1B9CRfKG3fulym")
req.Header.Set("Content-Type", "application/json")
res, err := http.DefaultClient.Do(req)
if err != nil {
panic(err)
}
defer res.Body.Close()
out, _ := io.ReadAll(res.Body)
fmt.Println(res.Status, string(out))
}require "net/http"
require "json"
uri = URI("https://api.mobilevalidate.com/v1/jobs")
req = Net::HTTP::Post.new(uri)
req["Authorization"] = "Bearer mv_test_publicSandboxn9ZgneuhR1B9CRfKG3fulym"
req["Content-Type"] = "application/json"
req.body = JSON.generate({
"numbers" => ["+447700900001"],
"checks" => ["line.registered"]
})
res = Net::HTTP.start(uri.host, uri.port, use_ssl: true) { |http| http.request(req) }
puts res.code, res.body// .mcp.json (Claude Code), ~/.cursor/mcp.json (Cursor) or .vscode/mcp.json ("servers" instead of "mcpServers")
{
"mcpServers": {
"mobilevalidate": {
"type": "http",
"url": "https://mcp.mobilevalidate.com/mcp",
"headers": { "Authorization": "Bearer ${MOBILEVALIDATE_API_KEY}" }
}
}
}
// Then ask your agent, e.g.:
// "Check +447700900001 with line.registered" → tool: create_lookup_jobThe hosted MCP server is live for customers with an agent key (mv_agent_…) or a test key. Or run it locally with npx -y @mobilevalidate/mcp.
Real test-mode result for this check
{
"service": "line.registered",
"status": "completed",
"registered": true,
"attributes": null,
"confidence": "high",
"confidence_score": 0.99,
"checked_at": "2026-09-25T14:25:28.979Z",
"cached": false,
"age_seconds": 0,
"billed": false,
"reason": null,
"poll_after_ms": null
}What you get
Fields of checks["line.registered"], generated from the public service catalog.
| Field | Type | Meaning |
|---|---|---|
| registered | boolean | null | true = found, false = not found, null = unknown (not charged). |
| status | enum | completed, pending, unknown, unsupported_country or failed. |
| checked_at | timestamp | When the answer was obtained. |
Frequently asked questions
Where is the LINE check most useful?
In markets where LINE is the main messenger, above all Japan, Taiwan and Thailand. The check accepts numbers from any country, but outside those markets most answers will be not registered.
Can a LINE account exist without a phone number?
LINE accounts are normally registered with a phone number, but people can also sign in with other login methods, and their number settings can differ. An account that is not linked to the number cannot be found through it.
Why is LINE bulk only?
LINE answers are gathered in batches, so the check runs in POST /v1/jobs. POST /v1/lookup refuses it with service_disabled.
Does the check return the LINE ID or display name?
No. Only whether an account is associated with the number. LINE IDs, display names and profile images are never returned.

