Skip to main content
HB
Automation
Freelance client -- Upwork

UK Planning Intelligence Scraper and CRM

FastAPI · Supabase · Idox Scraping · Proxy Rotation · Edge Functions

Hasan Iqbal Butt
By Hasan Iqbal ButtPublished: November 2024
0 MissedApplications Across 3 Clean Runs
01

The Challenge

The Buckinghamshire Council Idox planning portal renders content with JavaScript and uses JSESSIONID session-based pagination. Standard HTTP scraping returned empty pages because the portal requires an active session with valid CSRF tokens extracted from hidden form fields. The portal rate-limits aggressively, returning 429 responses that block the IP for extended periods. The HTML structure changes without notice, so the scraper would silently produce corrupt data when table layouts or CSS class names shifted. Duplicate records were a constant issue because the same planning application appears across multiple search result pages with slightly different formatting. The client needed every application within the Chiltern Beechwoods SAC Zone of Influence captured and scored, but the zone boundary is a geographic radius, not a simple postcode prefix list. A postcode-based filter missed applications at zone edges where postcodes straddle the boundary.

02

The Approach

The scraper engine has five modules totaling 1,107 lines. The HTTP client establishes a session by hitting the advanced search page to get a JSESSIONID cookie, then parses hidden form fields for CSRF tokens. It spoofs Chrome 145 on macOS with full Sec-Fetch and sec-ch-ua headers. Twenty residential proxies from Webshare rotate every seven requests with startup randomization and five-minute per-IP cooldown tracking on 429 responses. When rotating, the system clears cookies, re-initializes the session on the new IP, and extracts fresh CSRF tokens. The HTML parser uses BeautifulSoup with lxml to extract application details, agent contacts, postcodes via regex, and dwelling counts through three regex strategies in priority order. The catchment filter runs four steps on every application: geocode the postcode via postcodes.io, calculate Haversine distance from the SANG site and SAC boundary, check dwelling count thresholds by zone, filter by application type whitelist, and scan against seventy-six noise keywords. The lead scorer assigns points based on dwelling count, zone proximity, keyword matches, and application stage. Qualified applications are upserted into Supabase PostgreSQL keyed on reference number, preserving existing status and dwelling data on re-scrape. Supabase Edge Functions written in TypeScript on the Deno runtime handle confirmation and follow-up emails by posting to the FastAPI backend SMTP relay because Deno cannot open raw TCP sockets. HTML sanity checks validate page structure before parsing and upload raw snapshots to Supabase Storage on failure. The system deploys across three platforms: Vercel for the static React SPA frontend, Render for the FastAPI Docker container, and Supabase for database, auth, cron, edge functions, and storage.

03

System Architecture

Loading architecture diagram...
04

Deployment Topology

Deployment Topology

Three-platform architecture: Vercel, Render, and Supabase. Click a node to view its configuration details.

HTTPSSDKpg_cronScrapeGeocodeSMTPUPSERTWebhookRelayUser BrowserReact SPAVercelStatic HostingSupabase CloudPostgreSQL + Edge + CronRenderFastAPI ContainerIdox PortalBucks Council20 ProxiesWebshare Residentialpostcodes.ioGeocoding APIGmail SMTPGoogle WorkspaceEdge FunctionsDeno Runtime
Select a node to view infrastructure details
Primary data flow
SMTP relay delegation
05

Interactive Demo

Walk through the system design and data flow for this project step by step.

How the Planning Scraper Works

ScraperGET /searchIdox PortalJSESSIONIDCSRF TokensHidden FieldsSessionEstablishedUser-Agent: Chrome/145.0 macOSSec-Fetch-Site: same-origin | sec-ch-ua spoofed

Step 1Idox Portal Session Initialization

The scraper begins by establishing a valid session with the Buckinghamshire Council Idox planning portal. It sends a GET request to the advanced search page to receive a JSESSIONID cookie, then parses the HTML form to extract hidden fields containing CSRF tokens. These tokens are stored and included in every subsequent POST request. The request headers spoof Chrome 145 on macOS with full Sec-Fetch and sec-ch-ua headers to pass bot detection. If the session initialization fails on the current proxy IP, the system rotates to the next proxy and retries up to three times.

Key Insight

The Idox portal requires both a valid session cookie and CSRF tokens from hidden form fields for every search request. Without extracting these on each new proxy IP, the portal returns empty results. This is why simple HTTP scraping fails and why session re-initialization is mandatory on every proxy rotation.

1 of 8

06

Overview

Built a production planning application scraper and CRM for a UK conservation client. The system monitors Buckinghamshire Council Idox planning portal daily, runs a four-step catchment filter using Haversine distance calculations from the Chiltern Beechwoods SAC boundary, scores leads based on dwelling count and zone proximity, and automatically emails planning agents offering SANG credits. Twenty rotating residential proxies with per-IP cooldown tracking handle the portal rate limiting. Supabase provides PostgreSQL storage, Edge Functions for email automation, and pg_cron for daily scheduling. The validation confirmed zero missed applications across three consecutive runs.

07

Business Impact

The system replaced roughly eight hours per week of manual planning portal monitoring with a fully automated daily pipeline. Every qualified application within the five kilometer and twelve point six kilometer catchment zones is captured, scored, and emailed to the relevant planning agent within hours of appearing on the portal. The corpus audit across all scraped applications found zero missed applications after full deployment. Three consecutive identical clean runs confirmed no duplicates, no missed applications, and no false positives in the catchment filtering.

08

Technical Highlights

  • Idox portal scraper with JSESSIONID session management, CSRF token extraction, and browser fingerprint spoofing
  • 20 residential proxy rotation with round-robin cycling every 7 requests, startup randomization, and 5-minute per-IP cooldown on 429 responses
  • Structure-aware page classification into schedule, definition, preamble, and operative types for legal document parsing
  • 4-step catchment filter: Haversine distance from SANG/SAC boundary, dwelling count threshold, application type whitelist, 76-keyword noise filter
  • Lead scoring engine with base 25 points, zone proximity bonus, dwelling count multiplier, keyword hits, and noise penalties
  • Supabase Edge Functions for automated confirmation and follow-up emails via FastAPI SMTP relay
  • HTML sanity checks with HTMLStructureChangedError, raw HTML snapshot uploads to Supabase Storage, and alert emails on portal markup changes
  • Idempotent upserts keyed on planning reference number with status and dwelling data preservation on re-scrape
  • Historical backfill with stateful 2-day backward chunking via backfill_tracking table
  • pg_cron daily trigger at 07:00 UTC calling the FastAPI backend on Render

Want results like this for your infrastructure?

I specialize in taking complex AI pipelines and cloud setups from concept to high-availability production. Let's discuss how to optimize your workloads, secure your environment, and reduce cloud costs.