Quick-service restaurant (QSR) operators are high-value B2B targets for food service vendors, POS companies, and delivery platforms. This tutorial builds a pipeline that discovers QSR operators by brand and location, identifies multi-unit operators, and exports contact data. Each location search costs $0.005.
Prerequisites
- Python 3.8+
- requests library
- A Scavio API key from scavio.dev
- Target QSR brands and markets
Walkthrough
Step 1: Search for QSR franchise locations and operators
Find franchise locations and extract operator information from search results.
import os, requests, json, csv
from datetime import datetime
from collections import defaultdict, Counter
API_KEY = os.environ['SCAVIO_API_KEY']
SH = {'x-api-key': API_KEY, 'Content-Type': 'application/json'}
BRANDS = ['Subway', 'Chick-fil-A', 'Wingstop']
MARKETS = ['Dallas TX', 'Atlanta GA', 'Phoenix AZ']
def find_operators(brand, market):
queries = [
f'{brand} franchise owner {market}',
f'{brand} operator {market} locations',
]
operators = []
for query in queries:
data = requests.post('https://api.scavio.dev/api/v1/search',
headers=SH, json={'query': query, 'country_code': 'us'}, timeout=10).json()
for r in data.get('organic_results', []):
operators.append({
'brand': brand,
'market': market,
'title': r.get('title', ''),
'link': r.get('link', ''),
'snippet': r.get('snippet', '')[:150],
'source': r.get('displayed_link', ''),
})
return operators
all_operators = []
for brand in BRANDS:
for market in MARKETS:
ops = find_operators(brand, market)
all_operators.extend(ops)
print(f' {brand:15} in {market:12} | {len(ops)} results')
total_queries = len(BRANDS) * len(MARKETS) * 2
print(f'\nTotal results: {len(all_operators)}')
print(f'Cost: ${total_queries * 0.005:.3f}')Step 2: Extract and categorize operator data
Parse operator names, identify multi-unit operators, and categorize by source.
def categorize_results(operators):
categories = defaultdict(list)
for op in operators:
link = op['link'].lower()
if 'linkedin' in link:
categories['linkedin'].append(op)
elif 'businessjournals' in link or 'qsrmagazine' in link or 'nrn.com' in link:
categories['trade_press'].append(op)
elif 'franchisedisclosure' in link or 'franchise' in link:
categories['franchise_docs'].append(op)
else:
categories['other'].append(op)
print(f'\n=== Results by Source ===')
for cat, items in categories.items():
print(f' {cat:20} | {len(items)} results')
return categories
def find_multi_unit(operators):
"""Identify mentions of multi-unit operators (most valuable targets)."""
multi_unit = []
keywords = ['multi-unit', 'multi unit', 'franchise group', 'operates', 'locations',
'franchisee', 'largest operator']
for op in operators:
text = f'{op["title"]} {op["snippet"]}'.lower()
if any(kw in text for kw in keywords):
multi_unit.append(op)
print(f'\n=== Multi-Unit Operator Mentions ===')
print(f' Found: {len(multi_unit)} mentions')
for op in multi_unit[:5]:
print(f' [{op["brand"]}] {op["title"][:50]}')
print(f' {op["snippet"][:80]}')
return multi_unit
categories = categorize_results(all_operators)
multi_unit = find_multi_unit(all_operators)Step 3: Export operator list for outreach
Clean and export the operator list for sales team use.
def export_operator_list(operators, multi_unit):
# Deduplicate by link
seen = set()
unique = []
for op in operators:
if op['link'] not in seen:
seen.add(op['link'])
unique.append(op)
filename = f'qsr_operators_{datetime.now().strftime("%Y%m%d")}.csv'
with open(filename, 'w', newline='') as f:
writer = csv.DictWriter(f, fieldnames=['brand', 'market', 'title', 'link', 'source', 'snippet'])
writer.writeheader()
for op in unique:
writer.writerow({k: op[k] for k in writer.fieldnames})
print(f'\n=== QSR Operator Pipeline Summary ===')
print(f' Brands searched: {len(BRANDS)}')
print(f' Markets searched: {len(MARKETS)}')
print(f' Total results: {len(operators)}')
print(f' Unique results: {len(unique)}')
print(f' Multi-unit mentions: {len(multi_unit)}')
print(f' Exported to: {filename}')
# Brand breakdown
print(f'\n By Brand:')
brand_counts = Counter(op['brand'] for op in unique)
for brand, count in brand_counts.most_common():
print(f' {brand:15} | {count} results')
print(f'\n Cost: ${len(BRANDS) * len(MARKETS) * 2 * 0.005:.3f}')
print(f' vs. Data brokers: $500+ for QSR operator lists')
export_operator_list(all_operators, multi_unit)Python Example
import os, requests
SH = {'x-api-key': os.environ['SCAVIO_API_KEY'], 'Content-Type': 'application/json'}
def find_qsr_ops(brand, market):
data = requests.post('https://api.scavio.dev/api/v1/search',
headers=SH, json={'query': f'{brand} franchise owner {market}', 'country_code': 'us'}, timeout=10).json()
for r in data.get('organic_results', [])[:3]:
print(f' {r.get("title", "")[:50]}')
find_qsr_ops('Subway', 'Dallas TX')
print('Cost: $0.005')JavaScript Example
const SH = { 'x-api-key': process.env.SCAVIO_API_KEY, 'Content-Type': 'application/json' };
const data = await fetch('https://api.scavio.dev/api/v1/search', {
method: 'POST', headers: SH,
body: JSON.stringify({ query: 'Subway franchise owner Dallas TX', country_code: 'us' })
}).then(r => r.json());
(data.organic_results || []).slice(0, 3).forEach(r => console.log(r.title));Expected Output
Subway in Dallas TX | 14 results
Subway in Atlanta GA | 12 results
Chick-fil-A in Dallas TX | 10 results
Wingstop in Phoenix AZ | 11 results
Total results: 108
Cost: $0.090
=== Results by Source ===
linkedin | 18 results
trade_press | 25 results
franchise_docs | 15 results
=== Multi-Unit Operator Mentions ===
Found: 12 mentions
[Subway] Dallas Franchise Group Operates 45 Subway Loc
=== QSR Operator Pipeline Summary ===
Total results: 108
Unique results: 82
Multi-unit mentions: 12
Cost: $0.090