LinkedIn Phone Number Scraper By Region & City Targeting
Pricing
from $2.99 / 1,000 results
LinkedIn Phone Number Scraper By Region & City Targeting
LinkedIn Phone Number Scraper collects phone contact data to support workforce research and outreach. Analyze roles, sectors, or regions while identifying direct contact points efficiently.
Pricing
from $2.99 / 1,000 results
Rating
0.0
(0)
Developer
SimpleAPI
Maintained by CommunityActor stats
0
Bookmarked
17
Total users
3
Monthly active users
3 days ago
Last modified
Categories
Share
LinkedIn Phone Scraper — City and Region Targeting
LinkedIn Phone Region Targeter finds publicly indexed phone numbers tied to LinkedIn content for a keyword, country, and — uniquely — a specific list of cities or regions within that country, tagging every result with exactly where it was geo-targeted from. It's built for local sales teams who need leads scoped to a specific metro area rather than an entire country, franchise and multi-location businesses researching phone contacts city by city, and lead-generation teams who want a per-city breakdown of how many leads and distinct numbers a search actually surfaced. No LinkedIn login is required — every number comes from Google's own indexed search snippets. Every section below documents an input, an output field, or exactly how the city targeting and deduplication work.
What is LinkedIn Phone Region Targeter?
This Actor is a superset of a country-wide LinkedIn phone-number scraper: it still runs the same keyword-plus-country Google dork search, and adds a cities list that repeats each keyword's search once per named city, tagging every resulting row with the city it was found under and emitting a real aggregated summary row per city once the run finishes.
Key capabilities, read from the source:
- Per-city search + tagging.
process_keyword()insrc/main.pybuilds a separate Google query per city in yourcitieslist (viabuild_queries()), and every phone row it finds is tagged with thatcity— leavingcitiesempty preserves the original country-wide, city-less behavior exactly. - Verified locations, not echoed input. Every candidate page is fetched and its own
PostalAddress/ location line is read. A record whose page does not place it in the region you asked for is dropped, solocation,localityandregionare always the page's values. - Traceable phone provenance. Every row records
phoneSource,phoneSourceUrlandphoneSourceHost, so you can see exactly which document published each number and confirm it belongs to the entity in theurlfield. - GOOGLE_SERP-only proxying.
create_proxy_configuration()always routes through theGOOGLE_SERPApify proxy group specifically, because the module's own comment notes theRESIDENTIALgroup serves Google's JS-gated shell with no real results over plain HTTP —GOOGLE_SERPis the only group that reliably returns a real results page. - Genuine block detection, not a status-code guess.
fetch_html()classifies a response viais_block_page(), which inspects the actual response body rather than trusting the HTTP status alone, and retries with jitter before giving up on a query.
What data can I extract with LinkedIn Phone Region Targeter?
Every field in every row is read out of a page the Actor actually fetched. Nothing is
inferred from the search query and nothing is lifted from a Google snippet. A field that
cannot be sourced is omitted from the row — there are no "N/A" placeholders — and a
record that cannot be fully verified is dropped rather than emitted half-empty.
| Field | Example Value | Where it comes from |
|---|---|---|
phone_number | +442039954222 | Normalised to E.164 and validated against the target country's dial code |
phoneSource | about_section | Which part of which page published the number (see below) |
phoneSourceHost | uk.linkedin.com | The host the number was actually read from |
phoneSourceUrl | https://uk.linkedin.com/company/... | The exact document the number came from |
name / title | Growth Partners | <h1> of the fetched LinkedIn page |
entityType | company / person | Derived from the entity URL path |
headline | Business Consulting and Services | Industry / headline on the fetched page |
description | "...Call: +44 (0) 203 995 4222..." | The entity's own About text |
location | London, Greater London | The fetched page's own location line |
locality / region / streetAddress | London / Greater London / 160 Fleet Street | PostalAddress in the page's JSON-LD |
city | London | The region you requested — only present when the page's own location matched it |
url | LinkedIn entity URL | The verified profile / company page |
website | http://www.growthpartners.org | The entity's own external site, taken from the page |
keyword, platform, country, dial_code | Run scope |
Where a phone number can come from
phoneSource makes provenance explicit on every single row:
| Value | Meaning |
|---|---|
about_section | The organisation's own About us text on its LinkedIn page |
profile_tagline | The entity's own meta/tagline description |
own_post | A post whose JSON-LD author.url resolves to this same entity — its own content, never a third party's |
own_website | The entity's own external site, reached from the website link on its LinkedIn page |
LinkedIn exposes no structured telephone field to logged-out visitors, so a number is only
emitted when it appears in text the entity itself authored, or on the entity's own website.
Why not build this yourself?
Why not build this yourself?
LinkedIn does not expose phone numbers through any public API, and the only path to a public phone number tied to LinkedIn content is whatever Google has indexed in a page's visible snippet text — which means building and tuning a Google-dork query strategy, handling Google's own anti-automation detection (a "blocked" response often still returns HTTP 200 with a CAPTCHA-shaped body, not a clean error status), and routing through the specific proxy pool that actually returns real results rather than a JS-gated shell. This Actor already handles the correct proxy group selection, genuine body-based block detection with retry, and a query pattern that reliably surfaces LinkedIn-hosted content specifically — building that query and block-detection logic from scratch is most of the actual work.
How to use data extracted from LinkedIn Phone Region Targeter?
Local and regional sales teams
Set cities to your specific target metros within a country rather than running one broad country-wide search, and use the per-city summary rows to immediately see which cities produced the most leads before doing any manual review.
Franchise and multi-location businesses
Search a role or industry keyword across each of your franchise territories in one run. Because each row's locality and streetAddress come from the entity's own page, you can assign a lead to a territory on verified address data rather than on which search surfaced it.
Lead-generation and enrichment pipelines
Because every lead row already carries city and every summary row carries real aggregated counts, a pipeline can route leads to city-specific campaigns without any additional geocoding step.
Market coverage research
Compare how many verified leads each requested region yields for a given keyword to see where public, contactable coverage is densest. Because non-matching records are dropped rather than tagged, the per-region counts reflect real presence in that region.
🔼 Input sample
| Parameter | Required | Type | Description | Example Value |
|---|---|---|---|---|
keywords | Yes | array | Keywords, LinkedIn usernames, or profile URLs to search for. | ["plumber", "electrician"] |
country | Yes | string enum | Country to scope the search and dial-code matching to (full list of ~150 countries with dial codes). | "United Kingdom (+44)" |
cities | No | array | City/region names to geo-target within the selected country. Each keyword is searched once per city. Leave empty for a country-wide search. | ["London", "Manchester"] |
platform | No | string enum | Currently only "Linkedin". Default "Linkedin". | "Linkedin" |
maxPhoneNumbers | No | integer (1–10000) | Max phone numbers to collect per keyword. Default 20. | 50 |
useApifyProxy | No | boolean | Route through Apify Proxy (GOOGLE_SERP group). Default true. | true |
{"keywords": ["marketing"],"country": "United Kingdom (+44)","cities": ["London", "Manchester"],"maxPhoneNumbers": 30}
Common pitfall: maxPhoneNumbers caps new phone numbers per keyword, not per city — with multiple cities set, the cap is checked as leads accumulate across all cities for that keyword, so a keyword may reach its cap on an earlier city and collect nothing further from the remaining cities in that pass. Split a broad multi-city sweep into multiple keyword variants if you want a guaranteed minimum per city.
🔽 Output sample
One JSON row per verified phone lead, pushed to the run's default dataset and charged as one
row_result event per row. This is a real row from a live run:
{"recordType": "lead","platform": "Linkedin.com","keyword": "marketing consultant","city": "London","entityType": "company","name": "Growth Partners","title": "Growth Partners","headline": "Business Consulting and Services","description": "Growth Partners is a flexible consultancy platform with global capabilities... Call: +44 (0) 203 995 4222 Email: info@growthpartners.org","url": "https://uk.linkedin.com/company/growth-partners-consultancy","phone_number": "+442039954222","phoneSource": "about_section","phoneSourceUrl": "https://uk.linkedin.com/company/growth-partners-consultancy","phoneSourceHost": "uk.linkedin.com","location": "London","locality": "London","streetAddress": "160 Fleet Street","website": "http://www.growthpartners.org","country": "United Kingdom","dial_code": "+44"}
Note that region is absent from this row: LinkedIn published no addressRegion for this
company, so the key is omitted rather than filled with a guess.
How do you target specific cities and regions?
The city is verified against the fetched page, not just appended to a query. Appending a city name to a Google dork only biases which results come back — it proves nothing about where a record is. This Actor treats the city as a filter on real data:
- Each city becomes its own Google query, so
"marketing" in Londonandare two genuinely separate searches."marketing" in Manchester - Every candidate LinkedIn page is then fetched, and its own location is read from the
PostalAddressin its JSON-LD (addressLocality,addressRegion,streetAddress) or its top-card location line. - A record whose own page does not place it in the requested region is dropped, not emitted
with the requested city copied onto it. The
location,localityandregionyou get back are the page's values, not your input echoed back.
Because of step 3, a run can legitimately return fewer rows than candidates found — that is the filter working. The run log prints each drop and why.
Country subdomains are not location evidence. Google returns uk.linkedin.com,
ca.linkedin.com and similar host variants as a routing artefact. The Actor never treats the
subdomain as a location signal; only the fetched page's address fields count.
The per-keyword limit applies per region. maxPhoneNumbers is enforced for each
keyword and each requested region, so an early city cannot consume the whole budget and
starve the rest of your list.
Leaving cities empty runs a single country-wide pass per keyword with no region filter; rows
then carry no city key.
▶️ Want to try other LinkedIn scrapers?
| Scraper | What it extracts |
|---|---|
| LinkedIn Profile Contact Extractor | Contact details parsed from a profile |
| LinkedIn Company URL Mass Profile Finder | Bulk company URL discovery with executive contacts |
| LinkedIn Jobs Scraper — Employer & Company Details | Job postings with employer profile data |
| LinkedIn Comments and Reactions Scraper | Post comments, replies and reaction breakdown |
How to extract phone-number leads programmatically
This Actor runs as a standard Apify Actor call — one API call in, structured JSON dataset out, using your Apify API token.
Python example
from apify_client import ApifyClientclient = ApifyClient("<YOUR_API_TOKEN>")run = client.actor("<YOUR_USERNAME>/linkedin-phone-region-targeter").call(run_input={"keywords": ["marketing"],"country": "United Kingdom (+44)","cities": ["London", "Manchester"],})for item in client.dataset(run["defaultDatasetId"]).iterate_items():if item.get("recordType") == "lead":print(item["phone_number"], item["city"], item["url"])
Export to spreadsheets or CRM
Every dataset supports one-click CSV/Excel export from the Apify Console. Filter on recordType to separate lead rows from per-city summary rows before loading into a CRM.
Is it legal to scrape LinkedIn-linked phone numbers?
This Actor only surfaces phone numbers already published in Google's own publicly indexed search results — it does not access LinkedIn directly or bypass any LinkedIn login. Phone numbers tied to an identifiable individual are personal data under GDPR/CCPA, so treat storage and outreach accordingly, and be aware that unsolicited phone or SMS outreach is separately regulated in most jurisdictions (TCPA in the US, PECR in the UK, and equivalents elsewhere). Consult legal counsel before using this data for outbound calling or messaging campaigns.
❓ FAQ
Does maxPhoneNumbers apply per city or per keyword overall?
Per keyword and per region. Each requested city gets its own budget, so a city early in your list cannot exhaust the quota and leave later cities empty.
How do I know a phone number really belongs to the profile in the url field?
Every row carries phoneSource, phoneSourceUrl and phoneSourceHost. A number is only
accepted from the entity's own About text, its own tagline, a post whose JSON-LD author resolves
to that same entity, or the entity's own website — never from a comment, a caption, or another
company's content that happens to share the page.
Why are some fields missing from a row rather than empty?
Because the Actor never pads a record. If LinkedIn published no street address or region for a company, those keys are simply absent. Every key that is present holds a real, fetched value.
Do I need a LinkedIn account to use this?
No. Everything is read from publicly accessible pages. Note that LinkedIn returns HTTP 999 to un-proxied traffic and rate-limits per egress address, so the Actor rotates through a pool of proxy addresses and backs off automatically — leave the proxy enabled.
Why did a search return no phone numbers at all?
Either no candidate page in that region published a phone number in text the entity itself authored, or every candidate failed the region check. The run log lists each dropped candidate with the reason. Try a broader keyword or a larger region.
How does this compare to other LinkedIn phone-number scrapers?
As observed on the Apify Store on 2026-07-26, scraper-mind/linkedin-phone-number-scraper and api-empire/linkedin-profile-phone-number-scraper both extract phone numbers by keyword and country, but neither documents city/region-level targeting or a per-city aggregated summary row — that geo-targeting layer is unique to this Actor.
Does this work with AI agent frameworks?
Yes — call it as a standard HTTP endpoint via the Apify API from any agent framework capable of making an API call; there's no MCP-specific integration for this Actor.
Conclusion
LinkedIn Phone Region Targeter turns a keyword-and-country phone-number search into a city-scoped one — every lead tagged with where it was found, cross-city repeats tracked rather than duplicated or dropped, and a real aggregated summary per city. It fits local sales, franchise, and territory-based lead-generation work that needs geography built into the search itself. Start a run from the Apify Console or the Apify API with your target keywords, country, and cities to get your first geo-tagged lead export.