The Facebook check indicates whether a Facebook account is associated with a phone number. You get registered: true, false or null (unknown), plus the time of the check, in real time or in bulk jobs, for numbers in any country. Nothing is sent to the number, and no name, photo or profile is returned.
What does the Facebook check tell you?
It tells you whether the number is linked to a Facebook account. On Facebook the phone number is optional. People can sign up with a mobile number or an e-mail address, and they can add a number later to log in, recover a locked account or receive two-factor codes. A true answer therefore means the number was attached to an account at some point and is still attached.
registered: true: a Facebook account is associated with the number.registered: false: a conclusive "no". This happens often for genuine people who registered with e-mail only.registered: null: no conclusive answer.statusandreasonexplain why, and you are not charged.
Because the number is optional, false is weak evidence on its own. A true answer carries more weight: it means the number took part in Facebook's own verification when it was added.
Who uses it, and why?
Teams mostly use the Facebook check as one fraud-prevention signal among several. They rarely use it as a channel decision.
- Sign-up and OTP protection. Throwaway numbers used for fake sign-ups tend to have no history on large consumer platforms. A number with an associated Facebook account is less likely to be freshly generated. Combine the check with a carrier lookup to see the line type. See OTP and sign-up fraud.
- Lead verification. For consumer lead forms, an associated account suggests the number is a real, used mobile number rather than a typo.
- Account-security reviews. Changes to a recovery phone number are a common step in account takeover. Checking the new number's history is one input to a manual review.
Meta also runs Instagram, Threads and Messenger. People often link these accounts through Meta's Accounts Center, but each service has its own check. Request Instagram, Threads or Messenger in the same request.
What do you get back?
Each number gets one result under checks["facebook.registered"]. The service has no extra attributes.
| Field | Type | Meaning |
|---|---|---|
registered | boolean or null | true account associated, false none, null unknown |
status | enum | completed, pending, unknown, unsupported_country or failed |
confidence / confidence_score | enum / 0–1 | How sure the answer is; null when not conclusive |
checked_at | timestamp | When the answer was obtained |
cached / age_seconds | boolean / integer | Served from your account's cache, and its age |
billed | boolean | Whether this check was charged |
reason | string or null | Why an answer is not conclusive, e.g. UPSTREAM_TIMEOUT |
How is it billed?
You pay per number checked, and only for conclusive answers. You're not charged for inconclusive results (unknown, unsupported country, timeout, invalid, duplicate). Real-time lookups and bulk jobs are priced separately. See pricing for current rates.
Repeat checks of the same number inside the freshness window can come from your account's cache. Cache hits are free and marked cached: true, billed: false. Send max_age: 0 to force a fresh check, which is billed. Use max_cost to cap what a request may cost.
What are the limits?
The Facebook check runs in real time (POST /v1/lookup, up to 100 numbers per request) and in bulk jobs (POST /v1/jobs, up to 50,000 numbers and e-mails per job), for numbers from any country.
- A request can hold up to 20 checks. The total of numbers × checks is capped at 2,000 per lookup and 100,000 per job.
- Requests that look like sequential number ranges or generated e-mail lists are rejected (
suspected_enumeration). - Each account has a daily cap on the numbers it can check.
GET /v1/limitsshows what is left. - Invalid, duplicate and suppressed numbers are reported per row and not checked.
An answer can be unknown when the check does not complete in time. Answers that take longer than your wait come back as pending, and you can poll for them or receive them by webhook.
How do I use it responsibly?
Check only numbers you have a lawful reason to process, such as sign-ups, customers and consented leads. Treat the result as a risk signal, not a verdict on a person. Never use it to decide eligibility for credit, jobs, housing or insurance. The acceptable use policy forbids profiling individuals, working through number ranges to see who has an account, and unsolicited messaging.
Anyone whose number was checked can object through the opt-out form. Suppressed numbers are skipped and never charged.
Example request
Test keys (mv_test_…) are free and never reach a real network. +447700900001 always answers "registered". See test mode.
curl https://api.mobilevalidate.com/v1/lookup \
-H "Authorization: Bearer mv_test_publicSandboxn9ZgneuhR1B9CRfKG3fulym" \
-H "Content-Type: application/json" \
-d '{"numbers":["+447700900001"],"checks":["facebook"]}'// 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.lookup({
numbers: ["+447700900001"],
checks: ["facebook"],
});
if (error) console.error(error.code, error.message);
else console.dir(data.results, { 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/lookup", {
method: "POST",
headers: {
Authorization: "Bearer mv_test_publicSandboxn9ZgneuhR1B9CRfKG3fulym",
"Content-Type": "application/json",
},
body: JSON.stringify({
numbers: ["+447700900001"],
checks: ["facebook"],
}),
});
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.lookup(numbers=["+447700900001"], checks=["facebook"])
print(result)<?php
$ch = curl_init('https://api.mobilevalidate.com/v1/lookup');
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' => ['facebook'],
]),
]);
$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":["facebook"]}`)
req, err := http.NewRequest("POST", "https://api.mobilevalidate.com/v1/lookup", 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/lookup")
req = Net::HTTP::Post.new(uri)
req["Authorization"] = "Bearer mv_test_publicSandboxn9ZgneuhR1B9CRfKG3fulym"
req["Content-Type"] = "application/json"
req.body = JSON.generate({
"numbers" => ["+447700900001"],
"checks" => ["facebook"]
})
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.
Response (excerpt, test mode: the first item of results):
{
"kind": "phone",
"input": "+447700900001",
"e164": "+447700900001",
"country": "GB",
"number_status": "valid",
"checks": {
"facebook.registered": {
"service": "facebook.registered",
"status": "completed",
"registered": true,
"attributes": null,
"confidence": "high",
"confidence_score": 0.99,
"checked_at": "2026-09-25T14:25:30.545Z",
"cached": false,
"age_seconds": 0,
"billed": false,
"reason": null,
"poll_after_ms": null
}
},
"test": true
}Try it now
Realtime lookup via POST /v1/lookup. 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/lookup \
-H "Authorization: Bearer mv_test_publicSandboxn9ZgneuhR1B9CRfKG3fulym" \
-H "Content-Type: application/json" \
-d '{"numbers":["+447700900001"],"checks":["facebook.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.lookup({
numbers: ["+447700900001"],
checks: ["facebook.registered"],
});
if (error) console.error(error.code, error.message);
else console.dir(data.results, { 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/lookup", {
method: "POST",
headers: {
Authorization: "Bearer mv_test_publicSandboxn9ZgneuhR1B9CRfKG3fulym",
"Content-Type": "application/json",
},
body: JSON.stringify({
numbers: ["+447700900001"],
checks: ["facebook.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.lookup(numbers=["+447700900001"], checks=["facebook.registered"])
print(result)<?php
$ch = curl_init('https://api.mobilevalidate.com/v1/lookup');
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' => ['facebook.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":["facebook.registered"]}`)
req, err := http.NewRequest("POST", "https://api.mobilevalidate.com/v1/lookup", 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/lookup")
req = Net::HTTP::Post.new(uri)
req["Authorization"] = "Bearer mv_test_publicSandboxn9ZgneuhR1B9CRfKG3fulym"
req["Content-Type"] = "application/json"
req.body = JSON.generate({
"numbers" => ["+447700900001"],
"checks" => ["facebook.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 facebook.registered" → tool: lookup_numbersThe 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": "facebook.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["facebook.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
Does the result include the person's name or profile?
No. The check only indicates whether a Facebook account is associated with the number. No name, photo, profile link or activity is returned.
Is a Facebook account on a number proof of who the person is?
No. It is a signal that the number has been used to create or secure a Facebook account at some point. It is not identity verification and must not be used for eligibility decisions.
Why can a real, active person come back as not registered?
Facebook lets people sign up with an e-mail address instead of a phone number, and adding a number later is optional. Many genuine users simply never attached their number to the account.
Is the Messenger check the same as this one?
They are separate services. The Messenger check is available in bulk jobs only, while the Facebook check also works in real time. Request both in one job if you need both answers.
Is the check available for every country?
Yes, numbers from any country can be checked. National-format numbers need default_country so they can be converted to E.164.

