WhatsApp number filter: clean a list before a campaign
Phone lists rot. People switch numbers, forms collect typos, and spreadsheets mix 0612345678, +212 6 12 34 56 78 and 212612345678 in one column. Send a WhatsApp campaign to that list as it is, and a share of it goes nowhere.
wtsp.dev cleans it in one pass, and you only pay for real answers.
1. Add the country code
The one thing a lookup needs is the country code. Spaces, dashes, brackets, a leading + or 00 are all fine, so +212 6 12 34 56 78, 00212612345678 and 212612345678 are the same number. A national number like 0612345678 needs its country code in front, without the leading zero: 212612345678.
Not sure of a country's code? Every country page in lookups by country shows it, with a sample mobile number.
2. Send the whole list
You don't need to weed out bad rows first. A number that can't exist (wrong length, or a range no one has) is turned away before any payment is asked for, so typos cost nothing.
3. Keep the numbers that are on WhatsApp
Ask, for each number, whether it has WhatsApp. The exists lookup answers yes or no for 0.004 USDC, so a 10,000-row list costs $40. With a prepaid key (buy one in the API keys section), /v1/bulk checks 100 numbers per request.
const key = process.env.WTSP_API_KEY;
/** The numbers on WhatsApp, plus the ones to try again later. */async function clean(phones: string[]) { const keep: string[] = []; const retry: string[] = []; for (let i = 0; i < phones.length; i += 100) { const res = await fetch("https://wtsp.dev/v1/bulk", { method: "POST", headers: { Authorization: `Bearer ${key}`, "content-type": "application/json" }, body: JSON.stringify({ lookup: "exists", phones: phones.slice(i, i + 100) }), }); if (!res.ok) throw new Error(`HTTP ${res.status}`); for (const row of (await res.json()).results) { if (row.answer?.hasWhatsApp) keep.push(row.answer.phone); if (row.error?.code === "lookup_failed") retry.push(row.input); } } return { keep, retry };}What each row means for your bill:
- An
answeris charged whether it's yes or no. A no is just as useful: that row can go. invalid_phonemeans the number is malformed. Nothing is charged.lookup_failedmeans no answer this time. Nothing is charged; send those rows again in a minute.
The same number twice in one request is charged once. Each response gives what it charged and the balance left, so the job can stop before the credit runs out.
Rather not write code? Paste up to 1,000 numbers into our WhatsApp Number Checker on Apify and download the results as CSV or Excel. It's billed through your Apify plan.
Optional: learn more about the yeses
Once you know which numbers are on WhatsApp, a second pass can enrich them:
/v1/profile(0.006 USDC) tells personal accounts from business ones. Businesses come with their public profile: name, description, categories, email, websites, address and opening hours. That's handy for segmenting B2B lists./v1/carrier(0.002 USDC) gives the carrier and line type (mobile, fixed line or VoIP) of any number, on WhatsApp or not. Ported numbers show their original carrier.
The result
A list where every number has WhatsApp, with the typos and dead numbers gone. You sent it as it was, and paid only for the numbers that got an answer.
Try a few numbers on the playground first to see the answers before you run the whole list.