🌙 Contents
Shadow Rent Index: Real-Time Housing Inflation Oracle
Executive Summary
"Official inflation data looks in the rearview mirror. I wanted to build something that looks out the windshield."
The Shadow Rent Index is a fully automated, end-to-end data engineering project that tracks real-time rental spot prices in Madison, WI. It cuts through the 6 to 9 month lag baked into the government's official CPI shelter component. Every Sunday morning, a stealth ETL bot wakes up, scrapes hundreds of active listings, cleans the data, and loads everything into a PostgreSQL database. A Streamlit dashboard then shows interactive maps, neighborhood price averages, and supply levels, all pulled from current market prices and not year-old leases.
1. The Motivation: A Macroeconomic Blindspot
In my macroeconomics class, I learned that Shelter Cost makes up roughly one-third of the U.S. Consumer Price Index (CPI). But here is the catch: the Bureau of Labor Statistics calculates this number using existing lease agreements. That means rent prices that were locked in a year ago are still shaping what the government calls "today's inflation." The result is a structural lag of 6 to 9 months.
Living in Madison, WI, a fast-growing college town, I kept noticing a gap between what the news was saying and what my friends and I were actually experiencing. Official reports said inflation was cooling down, but landlords around campus were raising rents. Traditional economic indicators felt completely disconnected from real life. As a student studying Data Science and Economics, I wanted to try building something that could close that gap.
- The Problem: CPI shelter data lags the real rental market by 6 to 9 months because it relies on existing leases instead of current asking prices.
- The Hypothesis: Spot prices from active rental listings are a more sensitive and up-to-date signal of housing inflation.
- The Goal: Build an automated pipeline that collects those spot prices every week and visualizes them in a live dashboard.
2. ETL Pipeline Design
I designed the project around a classic Extract, Transform, Load (ETL) architecture. Each stage has a clear job to do:
- Extract: A Python scraper goes out every Sunday and pulls active rental listings from major real estate websites.
- Transform: A Pandas pipeline cleans the raw text, normalizes fields, and validates everything using Regular Expressions.
- Load: The clean records get appended to a PostgreSQL database via SQLAlchemy, slowly building up a historical timeline.
- Visualize: A Streamlit web app reads from the database and renders interactive Plotly Mapbox maps and price charts.
On paper, the plan looked straightforward. In practice, just the Extract step alone forced me to completely rethink my approach three separate times.
3. Challenges: Web Scraping Reality
Major real estate platforms are built to block scrapers, and I found that out the hard way. Here is what went wrong at the start:
- Dynamic DOM Manipulation: I built my first scraper with BeautifulSoup4, targeting specific HTML class names to grab prices and bedroom counts. It broke almost immediately. The site renders content through JavaScript and constantly shuffles its CSS class names, so any selectors I wrote became outdated within days.
- Anti-Bot Security: Cloudflare and similar systems kept detecting my requests, blocking my IP, and throwing CAPTCHAs at me. The standard Python
requestslibrary was getting fingerprinted and rejected before I could pull a single listing. - Data Quality Failures: Even on the rare occasions I got through the security layer, the shifting page layout would cause my parser to grab the wrong field. Instead of a bedroom count, I would sometimes get the square footage, which gave me hilarious results like a "2,850 bedroom" apartment.
"Every time I thought I had a stable scraper, the website would change something and break it all over again."
4. Engineering Solutions
Each problem needed its own fix. Here is how I worked through them:
Getting Past the Anti-Bot Wall: Stealth Browser Automation
I switched from the basic Python requests library to undetected-chromedriver, which spins up a headless Chrome browser that behaves much more like a real human user. It handles JavaScript rendering, sends realistic browser headers, and does not trip the same detection systems. I also added sleep intervals between page loads so the bot paces itself and does not overwhelm the server.
Fixing Fragile Selectors: Regex-Based Parsing
Instead of relying on HTML class names that keep changing, I switched to pulling the raw text content out of each listing block and using Regular Expressions to search for patterns. Prices almost always have a dollar sign followed by digits. Bedroom counts almost always end with the word "Bed." These text patterns are much more stable than CSS class names, so even when the website developers update their front-end code, the scraper keeps working.
Cleaning Up the Messy Data: Multi-Layer Validation
To prevent bad data from sneaking through, I added validation at two separate points:
- Transform phase: The Pandas pipeline converts raw strings to proper numeric types, drops any rows with null or out-of-range values, and enforces schema rules before anything touches the database.
- Query phase: The Streamlit app runs an additional SQL filter (
WHERE bedrooms < 20) as a final safety check, so even if a weird record somehow made it into the database, it will not show up on the dashboard.
5. The End Result: My Weekend Bot
In the end, I managed to build a fully automated system using Windows Task Scheduler. Now, every Sunday morning while I am still asleep, my stealth bot wakes up, quietly navigates the rental market, collects hundreds of active Madison listings, cleans the data, and safely tucks it into my PostgreSQL database.
My Streamlit dashboard then reads this fresh data to show an interactive map, average neighborhood prices, and supply levels. By tracking real-time spot prices instead of old leases, the Shadow Rent Oracle serves as a sensitive, up-to-date tracker for housing affordability. It was a fantastic learning experience that proved to me how powerful live data can be, and honestly, it is pretty cool to have a robot doing the heavy lifting while I enjoy my weekend!
6. Future Directions
Right now the system only covers Madison and pulls from a single platform. There are a few directions I would like to take it next:
- Multi-City Expansion: Run the same pipeline for other university towns like Ann Arbor, Austin, and Boulder to build a comparative national index.
- Multi-Platform Aggregation: Pull data from additional listing sources to reduce any bias from relying on just one website.
- CPI Comparison Layer: Add an overlay in the dashboard that shows the Shadow Rent Index against official BLS CPI shelter data side by side, so users can see the lag with their own eyes.
- Predictive Modeling: Use the growing historical dataset to train a forecasting model that tries to predict next month's average rent based on current supply and pricing trends.
- Cloud Deployment: Move the scheduler off my local machine and onto something like AWS Lambda so the pipeline does not depend on my computer being on.
Shadow Rent Index
Live Dashboard View Source Code