Find Local Businesses Without Websites: A Lead-Gen Goldmine for Web Designers

By Serpent API Team · · 11 min read

Walk down any small-town main street and you will see them: the family barber, the tyre shop, the taco truck, the boutique florist. Real businesses with real customers.

Many of them have no website. None at all. They live on word of mouth and a Google Maps pin.

If you sell web design, local SEO, or any digital service, that is not a problem. That is a list of pre-qualified leads waiting to be found.

This guide shows you how to find them at scale. We will loop over niche-and-city combinations, read Google's local results through a search API, flag the businesses with no website, and export a clean prospect CSV you can actually work from.

TL;DR: Roughly a quarter to a third of small businesses still have no website. Google's local pack lists the businesses for any "niche in city" search. With Serpent's Google SERP API you can pull those local listings (name, rating, reviews, category, address) in one call, then run a second search per business to confirm it has no site. Loop over many cities, dedupe, and export a CSV of warm leads. Flat pricing means scanning hundreds of cities costs only a few dollars.

Why "no website" is a goldmine

A business with no website is the warmest lead a web designer can get. They already have a budget signal (a real shop with overheads) and an obvious gap you can fill.

The opportunity is bigger than people think. A Top Design Firms survey of 500 U.S. small businesses found that 28% had no website at all, and 2025-2026 estimates still put the figure near 27%. In the trades, plumbing, roofing, landscaping, the share climbs well past 40%.

Now pair that with intent. When someone searches "electrician in Austin," Google shows a local pack: a map and a short list of nearby businesses pulled from Google Business Profiles. A business that appears there but has no website is losing customers every day to competitors who do.

That is your pitch, ready-made. You are not selling something they do not need. You are pointing at a leak and offering to fix it.

What the local pack actually gives you

The local pack returns the public facts a searcher sees: business name, star rating, review count, category, and address. That is exactly what Serpent's API exposes, and nothing it does not.

Honesty matters here, so let us be precise about the fields. When you call the API and read results.localPack, each entry looks like this:

FieldExampleUse it for
name"Riverside Auto Repair"The business identity
rating"4.7"Quality signal
reviews"126"How established they are
category"Auto repair shop"Niche fit
address"412 Main St"Your contact handle
hours"Open · Closes 6 PM"Context

Notice what is not on that list: there is no email field and no phone field in the local pack response, and there is no "website" URL field either. So we never claim to hand you an inbox or a dialer.

Instead, the absence of a website is something you confirm with a second, cheap search, which is exactly what makes this method honest and reliable. More on that in a moment. If you want a deeper tour of local-pack data, see our guide to scraping Google Maps data with Python.

The plan: from search to CSV

The pipeline is four simple stages, and each one maps to a few lines of Python.

1. Build your query grid. Take a list of niches ("dentist," "plumber," "hair salon") and a list of cities. The cartesian product gives you every "niche in city" search to run.

2. Pull the local pack. Call GET /api/search for each query and read results.localPack. Each search returns up to the businesses Google shows for that area.

3. Confirm no website. For each business, run a quick follow-up search for its name plus city. If no organic result clearly belongs to that business, mark it as a no-website lead.

4. Dedupe and export. Many cities overlap; the same shop can appear twice. Dedupe on name plus address, then write the survivors to a CSV.

That is the whole machine. Let us build it.

The full Python finder

Here is a complete, runnable script. It needs only the requests library and your Serpent API key, passed in the X-API-Key header.

import csv
import time
import requests

API_KEY = "sk_live_your_key"   # from https://apiserpent.com/login
BASE = "https://api.apiserpent.com"
HEADERS = {"X-API-Key": API_KEY}

# 1. Your search grid: niches x cities
NICHES = ["plumber", "roofer", "hair salon", "auto repair", "landscaper"]
CITIES = ["Tulsa OK", "Boise ID", "Fresno CA", "Akron OH"]


def get_local_pack(query):
    """Return the local pack businesses for one 'niche in city' search."""
    r = requests.get(
        f"{BASE}/api/search",
        headers=HEADERS,
        params={"q": query, "engine": "google", "country": "us"},
        timeout=120,
    )
    r.raise_for_status()
    data = r.json()
    return data.get("results", {}).get("localPack", [])


def has_website(name, city):
    """Search for the business by name. Returns True if it likely has a site."""
    r = requests.get(
        f"{BASE}/api/search/quick",
        headers=HEADERS,
        params={"q": f"{name} {city}", "engine": "google", "country": "us"},
        timeout=120,
    )
    r.raise_for_status()
    organic = r.json().get("results", {}).get("organic", [])

    # Domains that are directories, not the business's own site.
    DIRECTORIES = ("facebook.com", "yelp.com", "instagram.com",
                   "google.com", "maps.google", "tripadvisor.com",
                   "yellowpages.com", "mapquest.com", "bbb.org",
                   "linkedin.com", "nextdoor.com")

    for item in organic[:6]:
        url = (item.get("displayedUrl") or item.get("url") or "").lower()
        if any(d in url for d in DIRECTORIES):
            continue
        # A non-directory organic result in the top few = probably their site.
        return True
    return False


def find_leads():
    seen = set()
    leads = []
    for niche in NICHES:
        for city in CITIES:
            query = f"{niche} in {city}"
            print(f"Searching: {query}")
            try:
                pack = get_local_pack(query)
            except requests.HTTPError as e:
                print(f"  skip ({e})")
                continue

            for biz in pack:
                name = biz.get("name")
                addr = biz.get("address") or ""
                if not name:
                    continue
                key = (name.lower(), addr.lower())
                if key in seen:
                    continue
                seen.add(key)

                if has_website(name, city):
                    continue   # already has a site, not our lead

                leads.append({
                    "name": name,
                    "category": biz.get("category") or niche,
                    "rating": biz.get("rating") or "",
                    "reviews": biz.get("reviews") or "",
                    "address": addr,
                    "city": city,
                    "found_via": query,
                })
                print(f"  LEAD (no website): {name}")
            time.sleep(0.3)   # be gentle
    return leads


def export_csv(leads, path="leads_no_website.csv"):
    fields = ["name", "category", "rating", "reviews",
              "address", "city", "found_via"]
    with open(path, "w", newline="", encoding="utf-8") as f:
        w = csv.DictWriter(f, fieldnames=fields)
        w.writeheader()
        w.writerows(leads)
    print(f"\nWrote {len(leads)} leads to {path}")


if __name__ == "__main__":
    leads = find_leads()
    export_csv(leads)

Run it with python finder.py. You get a leads_no_website.csv with one row per prospect: the name, category, rating, review count, address, the city it was found in, and the exact query that surfaced it.

The structure is intentionally close to the one in our SERP API lead generation guide, so you can reuse the same scaffolding for other lead types.

Tip: Want to add a geographic spread check, like whether a shop ranks across a whole city grid? Our geo-grid local rank tracker tutorial shows how to run the same query from many map points, which is a Local Falcon-style approach you can bolt onto this finder.

Confirming "no website" honestly

The single most important rule: never tell a prospect "you have no website" unless you have actually checked. A false claim kills your credibility in the first sentence.

Our has_website() function does the heavy lifting. It searches for the business by name and city, then ignores directory domains (Facebook, Yelp, Google Maps and friends). A Facebook page is not a website; it is exactly why they still need you.

If the top results are all directories, that is a strong "no real site" signal. If a clean, business-owned domain shows up, the script drops the lead automatically.

This two-step approach, list the local businesses, then verify each one, is what keeps the method accurate. The local pack tells you who exists; the second search tells you who has a gap. Reading raw organic results well is its own skill; our guide to scraping Google results in Python covers the parsing patterns in depth.

Before any outreach, open the two or three best leads in a browser yourself. A 30-second human check stops you from emailing a business that does have a site the script just missed.

Turning leads into clients

A CSV is not money; a conversation is. The good news is that "you show up on Google but have no website" is one of the easiest openers in sales.

Lead with the specific, true observation. Something like: "I searched for plumbers in Tulsa and found Riverside Plumbing on the map with a great 4.8 rating, but I could not find a website. Customers comparing you to nearby competitors may be picking the one they can read about online."

Then offer one concrete, low-friction next step, not a 12-page proposal. A one-page mockup of their homepage, built before the call, converts far better than a sales pitch.

On pricing, anchor to the value of one extra customer. For a local trade, a single new job can be worth hundreds of dollars, which makes a few-hundred-dollar starter site or a small monthly care plan an easy yes.

OfferTypical rangeBest for
One-page "card" site$300 - $800Solo trades, food trucks
Standard 5-page site$800 - $2,500Established shops
Site + monthly care plan$50 - $150/moRecurring revenue

Because the address is your contact handle (remember, the API does not return a phone number), the highest-converting channel is often a polite in-person visit or a mailed postcard, not a cold email. That feels old-fashioned, and that is precisely why it works for businesses that still run on handshakes.

Scaling across cities cheaply

The whole reason this is a business and not a hobby is cost. Scanning a single city is fine; scanning a hundred is where the volume of leads becomes serious.

Serpent uses flat per-call pricing for Google search. It starts at $0.60 per 10,000 searches and drops to $0.06 per 10,000 at the Growth tier and $0.03 per 10,000 at Scale. Crucially, page depth does not multiply the price, so a deep search costs the same as a quick one.

Do the math on a real campaign. Five niches across a hundred cities is 500 local-pack searches. Each surfaces a handful of businesses, and each business costs one more search to verify. Even at a few thousand total calls, you are spending single-digit dollars to build a list of hundreds of warm prospects.

Campaign sizeApprox. API callsCost at $0.60/10K
5 niches × 10 cities~600under $0.05
5 niches × 100 cities~6,000~$0.36
10 niches × 250 cities~30,000~$1.80

There is no proxy pool or headless browser to babysit; the API handles access for you, so your script stays a script. You also get up to 100 organic results in a single deep call when you need them, and 10 free Google searches to test the whole flow before you spend a cent. If you are wiring this into a product, our notes on using a SERP API inside a SaaS cover rate limits and caching.

Staying ethical and legal

You are reading public business listings and public search results, the same information any person sees in a browser. For B2B prospecting that is broadly accepted, but how you use it is what matters.

Do not blast generic spam. Anti-spam rules like the U.S. CAN-SPAM Act and similar laws elsewhere apply to commercial messages, and unsolicited cold email at volume is both illegal in places and ineffective everywhere. Lead with genuine, specific value instead.

Respect "no." If a business says they are not interested, take them off your list and keep them off. A clean reputation is worth more than any single lead.

Finally, keep your data fresh. A shop without a website today may have one next quarter, so re-verify before each outreach round. Pairing this finder with ongoing local SEO rank tracking turns a one-off list into a living pipeline you can also upsell SEO work into.

Build your no-website lead list this week

Serpent's Google SERP API hands you clean local-pack and organic data in one call, with no proxies or browsers to manage. Start with 10 free Google searches, flat pricing from $0.03 per 10,000 searches, and no subscription.

Get Your Free API Key

Explore: Google SERP API · Lead Generation Guide · Pricing

FAQ

How many small businesses still have no website?

Surveys consistently put it around a quarter to a third. A Top Design Firms survey of 500 U.S. small businesses found 28% had no website, and 2025-2026 estimates still hover near 27%. Trades and contractors run far higher, often 40% or more.

Does Serpent API return a phone number or website for local pack results?

The localPack field returns name, rating, reviews, category, address, and hours. It does not return a phone number or a website URL field, so you confirm a missing website by running a second search for the business name and checking whether an official site appears.

How do I confirm a business truly has no website?

Take the business name plus its city and run a normal web search for it. If no organic result clearly belongs to that business, treat it as a no-website lead. Always do a quick manual double-check before reaching out.

Is it legal to collect this lead data?

You are reading publicly visible business listings and public search results, the same data a person sees in a browser. That is generally fine for B2B prospecting. Follow anti-spam laws for outreach and respect any do-not-contact requests.

How much does it cost to scan many cities?

Serpent uses flat per-call pricing for Google search, starting at $0.60 per 10,000 searches and dropping to $0.03 per 10,000 at the Scale tier. Page depth does not multiply the price, so scanning hundreds of niche-and-city pairs costs only a few dollars.