Ask ChatGPT Ask Claude

Phone number scam lookup API

Bewary's phone API checks numbers against its scam list, which includes numbers from FTC and FCC complaints and Germany's Federal Network Agency (BNetzA) actions. It returns the country and number type from the numbering plan. With `line_type=true`, it adds the live line type from the carrier network. A number named only as caller ID in unwanted-call complaints carries `PHONE_REPORTED_CALLER_ID`, a caution, and is not listed. A call costs 1 credit (10 with line_type=true), a free key gets 1,000 credits a month, no card, and it answers in median 115 ms.

Endpoint
GEThttps://api.bewary.app/v1/phone/{number}
Price
1 credit, line_type=true 10
Free key
1,000 credits a month, no card
Speed
Median 115 ms, measured
Returns
verdict, p_scam, entities with typed facts, reason codes
MCP tool
lookup_phone

Try it

Free from this page: 10 lookups a day
GET/v1/phone/{number}
Recorded answer, October 31, 2026
Unknownp_scam0.2000
Entities
phone+18008291040Unknown

Call it

curl "https://api.bewary.app/v1/phone/%2B18008291040"

Act on the result

Copy-paste code that turns the answer into a decision. It runs with or without BEWARY_API_KEY. TypeScript uses bewary.d.ts.

import os, requests
from urllib.parse import quote

def caller_label(number):
    key = os.environ["BEWARY_API_KEY"]          # a free key: bewary.app/account
    headers = {"Authorization": f"Bearer {key}"}
    r = requests.get("https://api.bewary.app/v1/phone/" + quote(number), headers=headers, timeout=10)
    r.raise_for_status()
    result = r.json()
    if result["entities"][0]["facts"]["listed"]:
        return "Reported for scam calls"
    return None                            # no label: not listed is not proof of safe

print(caller_label("+18008291040"))

Response

The fields you will use

verdict
scam when the number is on our list, otherwise usually unknown.
entities[0].facts.listed
On Bewary's scam list.
entities[0].facts.number_type
From the numbering plan: toll_free, mobile, landline and more.
entities[0].facts.line_type
With line_type=true: the live line type.
Example responses
{  "schema_version": "1.7.0",  "request_id": "req_01M69WHKA2ETH25TQA4J813VRP",  "checked_at": "2026-10-31T21:06:15Z",  "engine": "bewary-engine/3.0.0",  "models": {    "calibration": "interim-band-v0"  },  "input": {    "kind": "lookup",    "channel": "unknown",    "language": null,    "region": null  },  "verdict": "unknown",  "p_scam": 0.2,  "risk_score": 20,  "confidence": 0,  "classification": null,  "reason_codes": [],  "entities": [    {      "id": "e1",      "type": "phone",      "value": "+18008291040",      "normalized": "+18008291040",      "role": "mentioned",      "verdict": "unknown",      "p_scam": 0.2,      "risk_score": 20,      "reason_codes": [],      "facts": {        "e164": "+18008291040",        "country": "US",        "number_type": "toll_free",        "original_carrier": null,        "line_type": null,        "complaints": {          "ftc": null,          "fcc": null,          "callbacks": null,          "pushed_by": null        },        "honeypot_hits_30d": 0,        "listed": false,        "public_listing": null,        "indexable": false,        "target_countries": null,        "list_count": null      },      "related": [],      "datasets": [        {          "dataset": "phone_numbering",          "coverage": "WW",          "in_coverage": true        },        {          "dataset": "us_numbering",          "coverage": "US",          "in_coverage": true        },        {          "dataset": "phone_complaints",          "coverage": "US",          "in_coverage": true        },        {          "dataset": "honeypot_lines",          "coverage": "US",          "in_coverage": true        },        {          "dataset": "phone_reports_de",          "coverage": "DE",          "in_coverage": false        },        {          "dataset": "community_reports",          "coverage": "WW",          "in_coverage": true        }      ]    }  ],  "signals": [],  "degraded": false,  "degraded_reasons": [],  "cached": false,  "explanation": null}

Real responses, captured from the live API on 2026-10-31. Every response has this shape: see Response format.

Phone number facts

Every key is in every response, null when unknown. A key marked Coming stays null until its source ships, so you can code against it now.

KeyTypeMeaning
e164 string or null The number in E.164 form.
country ISO code or null Country from the numbering plan.
number_type mobile | landline | voip | toll_free | premium | shared_cost | shortcode | unknown or null Type from the numbering plan.
line_type same values or null With line_type=true: the live line type from the carrier network.
listed boolean or null On Bewary's scam list.
complaints object or null FTC and FCC complaints from the last 13 months, one entry per source (null when that source has none): count, days, first and last date, subjects, robocall share, the count per day for 90 days and the top five states of the people who complained.
indexable boolean or null Whether the number has a page in the number directory: two independent signals, such as complaints on two or more days, or FTC and FCC complaints.
original_carrier string or null The carrier the number block was first assigned to.
target_countries array or null Countries whose people it is aimed at, from the national lists that name it (PL, TW, DE, US).
list_count integer or null How many lists name it, ours and others'.
honeypot_hits_30d integer or null Calls to our honeypot lines in 30 days.

Parameters

NameTypeDescription
numberpath, required string The number in E.164 form, e.g. +18008291040. A national number needs region.
line_typequery boolean Add the live line type: mobile, landline or VoIP (10 credits, API key required). Default false.
regionquery string ISO country code for reading a national number, e.g. US.

Questions

Is there an API that says if a phone number is a scam?

Yes, GET /v1/phone/{number} checks Bewary's scam list. Bewary reads FTC Do Not Call and FCC complaints hourly and Germany's Federal Network Agency (BNetzA) actions daily. Numbers named only as caller ID in unwanted-call complaints stay unknown unless other evidence names them. Your code must never treat unknown as safe.

Can it detect VoIP numbers?

With line_type=true (10 credits, API key), facts.line_type gives the live line type, VoIP included. The free number_type comes from the numbering plan, which for US numbers often cannot tell mobile from landline.

Does it return the owner's name?

No. Bewary never returns a person's name for a number.

Is a listed number always a scammer?

Bewary's scam list includes numbers pushed as callback numbers in calls and numbers named in national lists such as BNetzA's actions against phone numbers. Since contract 1.2.0, a number named only as caller ID carries the caution PHONE_REPORTED_CALLER_ID and stays unknown without a scam listing.

Used for

Reason codes it can return

CodeMeaningSeverity
LISTED_BLOCKLISTOn scam blocklistCritical
PHONE_INVALIDInvalid numberMedium
PHONE_UNPARSEABLENumber unreadableInfo
PHONE_VOIPVoIP / virtual numberMedium
PHONE_RISK_FLAGGEDFlagged numberMedium
PHONE_PUBLIC_SCAM_REPORTSReported scam numberMedium
PHONE_NO_PUBLIC_LISTINGNo public listingInfo
PHONE_FTC_COMPLAINTSComplaints about this number at the FTCMedium
PHONE_FCC_COMPLAINTSComplaints about this number at the FCCMedium
PHONE_HONEYPOT_HITCalled our honeypot linesHigh
LISTED_CAUTIONOn a broad threat list that also holds spam and malware hostsMedium
PHONE_REPORTED_CALLER_IDShown as the caller ID of complained-about calls, which callers can fakeMedium
PLATFORM_TAKEDOWNThe hosting platform took it downHigh
PLATFORM_WARNINGThe platform shows a phishing or malware warning in front of itHigh

Reserved codes are in the contract, not emitted yet. All reason codes

Updated · This page as Markdown · Changelog