TypeScript: Lookup Verified Phone Numbers from LinkedIn

Imagine dialing a lead's real number, verified from their LinkedIn. This TypeScript snippet makes it dead simple—one API call, and you're in business. Sales teams, rejoice.

One TypeScript Call to Unlock Verified Phones from LinkedIn Handles — theAIcatchup

Key Takeaways

  • Single TypeScript fetch unlocks verified phones from LinkedIn handles—no extra libs needed.
  • Batch process lists with rate limits and retries for production sales pipelines.
  • Composable API brick powers AI sales agents and replaces $150+/mo tools like Clay.

What if the phone number hiding behind every LinkedIn profile could supercharge your sales pipeline—without the guesswork, without dead ends?

TypeScript developers, listen up: looking up verified phone numbers from social handles isn’t some dark art anymore. It’s a single fetch call to the Million Phones API. And yeah, it’s that straightforward. We’re talking real mobile numbers for outbound sales, CRM blasts, or whatever pipeline you’ve got cooking.

Picture this—like a digital bloodhound sniffing out treasure. You feed it a LinkedIn handle (williamhgates, say), and boom: +1-833-457-0192 pops out, verified and ready to ring.

How Do You Look Up Verified Phone Numbers with TypeScript?

Grab your terminal. mkdir phone-lookup && cd phone-lookup. npm init -y, then npm install tsx. No bloaty HTTP libs—Node 18+’s fetch does the heavy lifting.

Here’s the heart of it, lookup.ts:

interface PhoneResponse {
  phone_numbers: string[];
}

async function lookupPhone(socialUrl: string): Promise<string[] | null> {
  const apiKey = process.env.MILLIONPHONES_API_KEY;
  if (!apiKey) {
    throw new Error("Missing MILLIONPHONES_API_KEY environment variable");
  }
  const url = `https://millionphones.com/v1/phone?social_url=${encodeURIComponent(socialUrl)}`;
  const response = await fetch(url, {
    headers: {
      "x-api-key": apiKey,
    },
  });
  if (!response.ok) {
    console.error(`Lookup failed: ${response.status} ${response.statusText}`);
    return null;
  }
  const data = (await response.json()) as PhoneResponse;
  return data.phone_numbers?.length ? data.phone_numbers : null;
}

Tack on a runner:

async function main() {
  const handle = process.argv[2];
  if (!handle) {
    console.log("Usage: npx tsx lookup.ts <linkedin-handle>");
    process.exit(1);
  }
  console.log(`Looking up: ${handle}`);
  const phones = await lookupPhone(handle);
  if (phones) {
    phones.forEach((phone) => console.log(`✅ ${phone}`));
  } else {
    console.log("❌ No verified number found");
  }
}
main();

Export your key—MILLIONPHONES_API_KEY=your_key_here—then npx tsx lookup.ts williamhgates. Watch it deliver.

But wait. Single handles? Cute for demos. Real sales grind through lists.

Why Does Verified Phone Data Feel Like the New Email Gold Rush?

Back in the 2010s, email verification APIs flipped outbound sales on its head—cold emails started hitting inboxes, not spam folders. Now? Phones. Voice calls, AI agents dialing autonomously, SMS bursts. Verified mobiles are the frontier. My bold call: within two years, every AI sales copilot will demand this exact pipe. Million Phones isn’t hype; it’s the pickaxe for that gold rush.

The original code nails batching:

Most real pipelines need to process a list, not a single handle. Here’s a version that reads from a file and respects rate limits.

Smart. Drop handles into handles.txt, one per line. Then tweak your script:

import { readFileSync, writeFileSync } from "fs";

async function batchLookup(inputFile: string, outputFile: string) {
  const handles = readFileSync(inputFile, "utf-8")
    .split("\n")
    .map((line) => line.trim())
    .filter(Boolean);
  console.log(`Processing ${handles.length} handles...`);
  const results: { handle: string; phones: string[] | null }[] = [];
  for (const handle of handles) {
    const phones = await lookupPhone(handle);
    results.push({ handle, phones });
    // Simple rate limiting — 200ms between requests
    await new Promise((resolve) => setTimeout(resolve, 200));
  }
  writeFileSync(outputFile, JSON.stringify(results, null, 2));
  console.log(`Results written to ${outputFile}`);
}

npx tsx lookup.ts –batch handles.txt results.json. Boom—JSON output, rate-limited, clean.

And retries? Because APIs flake.

async function lookupWithRetry(
  socialUrl: string,
  retries = 3
): Promise<string[] | null> {
  for (let attempt = 1; attempt <= retries; attempt++) {
    try {
      const result = await lookupPhone(socialUrl);
      if (result) return result;
    } catch (err) {
      console.error(`Attempt ${attempt} failed:`, err);
      if (attempt < retries) {
        await new Promise((r) => setTimeout(r, 1000 * attempt));
      }
    }
  }
  return null;
}

Exponential backoff—classic, battle-tested.

Look, this isn’t just a script. It’s a composable brick for your GTM fortress.

Is Million Phones API the Sales Dev’s Secret Weapon?

This is the building block for a composable GTM stack — no spreadsheet UI, no credit-based pricing, just a script that does what you need. Plug this into a Supabase database, sync results to Google Sheets for your SDRs, and you’ve replaced most of what tools like Clay charge $150+/month for.

Jack at Million Phones gets it—no clunky dashboards, pure API. Free tier: 50 credits. Docs at millionphones.com/docs.

But here’s my twist, the insight you won’t find in the tutorial: this unlocks AI-augmented sales fleets. Imagine agents scraping LinkedIn, verifying phones on-the-fly, dialing prospects while you sip coffee. It’s not if—it’s when. TypeScript’s type safety makes it enterprise-ready; no runtime surprises derailing your quota.

Sales teams drowning in unverified leads? Dead. This flow—fetch, verify, pipe to CRM—mirrors how REST APIs democratized data in the web2 era. Phones are web3 for voice.

Scale it. Hook to Supabase for storage. Zapier to Sheets. Or go full Node microservice. Your SDRs get hot lists; you get velocity.

One caveat—rate limits. That 200ms sleep? Tune it, or you’ll hit walls. Pro tip: queue with BullMQ for prod.

And privacy? Verified means consented paths—LinkedIn public data, ethically sourced. No scraping skeeze.

This snippet? It’s future-proof. Node evolves, fetch sticks, TypeScript types guard your ass.

Energy here is palpable—sales just got programmable, verifiable, instant.

Plugging It into Your Stack: Real-World Flows

Start small: CLI for ad-hoc lookups. Then batch nightly against your leads DB.

Next level—webhook from HubSpot: new lead? Auto-phone-hunt.

AI twist: pipe to LangChain agent. “Call top 10 prospects today.” Done.

Costs? Free tier tests waters. Scales flat—no per-credit BS.

Skeptical? Run it on your list. Gates’ number worked. Yours will too.


🧬 Related Insights

Frequently Asked Questions

What is the Million Phones API?

It’s a simple REST API that returns verified mobile numbers from LinkedIn profile URLs. One param: social_url. Free 50 credits to start.

How to get verified phone numbers from LinkedIn with TypeScript?

Use the lookupPhone function above—fetch with API key, parse JSON. Handles singles or batches from files.

Does Million Phones API work for sales teams?

Absolutely. Replaces pricey no-code tools. Integrate with CRMs, sheets—pure code, your rules.

James Kowalski
Written by

Investigative tech reporter focused on AI ethics, regulation, and societal impact.

Frequently asked questions

What is the Million Phones API?
It's a simple REST API that returns verified mobile numbers from LinkedIn profile URLs. One param: social_url. Free 50 credits to start.
How to get verified phone numbers from LinkedIn with TypeScript?
Use the lookupPhone function above—fetch with API key, parse JSON. Handles singles or batches from files.
Does Million Phones API work for sales teams?
Absolutely. Replaces pricey no-code tools. Integrate with CRMs, sheets—pure code, your rules.

Worth sharing?

Get the best AI stories of the week in your inbox — no noise, no spam.

Originally reported by Dev.to

Stay in the loop

The week's most important stories from theAIcatchup, delivered once a week.