Real estate buyers check Zillow, Realtor.com, and Redfin separately. An aggregation agent searches all platforms via SERP API, consolidates listings, and catches price differences. This tutorial builds one using site-specific Google searches at $0.005 each.
Prerequisites
- Python 3.8+
- requests library
- A Scavio API key from scavio.dev
- Target neighborhoods or zip codes
Walkthrough
Step 1: Build platform-specific search queries
Use site: queries to target each real estate platform.
import os, requests, re
API_KEY = os.environ['SCAVIO_API_KEY']
H = {'x-api-key': API_KEY, 'Content-Type': 'application/json'}
def search_platform(location, site):
data = requests.post('https://api.scavio.dev/api/v1/search',
headers=H, json={'query': f'site:{site} homes for sale {location}', 'country_code': 'us'}).json()
results = []
for r in data.get('organic_results', [])[:5]:
prices = re.findall(r'\$[\d,]+', r.get('snippet', ''))
results.append({'title': r['title'], 'url': r['link'], 'prices': prices, 'source': site})
return resultsStep 2: Aggregate across platforms
Search all platforms and merge results.
def aggregate(location):
all_listings = []
for site in ['zillow.com', 'realtor.com', 'redfin.com']:
results = search_platform(location, site)
all_listings.extend(results)
print(f' {site}: {len(results)} results')
print(f'Total: {len(all_listings)} listings, Cost: $0.015')
return all_listings
listings = aggregate('Austin TX 78704')Step 3: Detect cross-platform price differences
Find the same property on multiple platforms with different prices.
from collections import defaultdict
def find_gaps(listings):
by_addr = defaultdict(list)
for l in listings:
words = l['title'].lower().split()
nums = [w for w in words if w[0].isdigit()]
if len(nums) >= 1:
by_addr[nums[0]].append(l)
for addr, sources in by_addr.items():
if len(sources) > 1:
print(f' {addr}: found on {len(sources)} platforms')
for s in sources:
print(f' {s["source"]}: {", ".join(s["prices"]) or "N/A"}')
find_gaps(listings)Step 4: Monitor for new listings daily
Track seen URLs and alert on new listings.
import json
def monitor(location, state_file='seen.json'):
try:
with open(state_file) as f: seen = set(json.load(f))
except FileNotFoundError: seen = set()
listings = aggregate(location)
new = [l for l in listings if l['url'] not in seen]
print(f'{len(new)} new listings')
for l in new[:5]: print(f' [{l["source"]}] {l["title"][:50]}')
seen.update(l['url'] for l in listings)
with open(state_file, 'w') as f: json.dump(list(seen), f)
monitor('Austin TX 78704')Python Example
import os, requests, re
API_KEY = os.environ['SCAVIO_API_KEY']
H = {'x-api-key': API_KEY, 'Content-Type': 'application/json'}
def search(location, site):
data = requests.post('https://api.scavio.dev/api/v1/search',
headers=H, json={'query': f'site:{site} homes {location}', 'country_code': 'us'}).json()
for r in data.get('organic_results', [])[:3]:
prices = re.findall(r'\$[\d,]+', r.get('snippet', ''))
print(f' [{site}] {r["title"][:40]} | {", ".join(prices) or "N/A"}')
for s in ['zillow.com', 'realtor.com']: search('Austin TX', s)JavaScript Example
const API_KEY = process.env.SCAVIO_API_KEY;
const H = { 'x-api-key': API_KEY, 'Content-Type': 'application/json' };
async function search(location, site) {
const data = await fetch('https://api.scavio.dev/api/v1/search', {
method: 'POST', headers: H,
body: JSON.stringify({ query: `site:${site} homes ${location}`, country_code: 'us' })
}).then(r => r.json());
(data.organic_results || []).slice(0, 3).forEach(r => {
const prices = (r.snippet || '').match(/\$[\d,]+/g) || [];
console.log(` [${site}] ${r.title.slice(0, 40)} | ${prices.join(', ') || 'N/A'}`);
});
}
(async () => { for (const s of ['zillow.com', 'realtor.com']) await search('Austin TX', s); })();Expected Output
zillow.com: 5 results
realtor.com: 4 results
redfin.com: 5 results
Total: 14 listings, Cost: $0.015
1234: found on 2 platforms
zillow.com: $549,000
redfin.com: $545,000