Skip to main content

Real estate investment research data pipeline for US metros and cities

Project description

Cityscope

Find your next real estate market in minutes, not months.

Python 3.13+ Data Sources SQLite PyPI License


A pip-installable Python package that pulls public government data about every major US metro and city — population growth, job growth, wages, unemployment — and stores it locally in SQLite for analysis. Use it as a library, from the CLI, or build your own UI on top.

Install

pip install cityscope

Or with uv:

uv add cityscope

Python API

from cityscope import api

# Fetch data from public sources
api.fetch("census_population")
api.fetch("bls_employment", skip_laus=True)

# Query as a DataFrame
df = api.to_dataframe(metric="population_change_pct", geo_type="metro", year=2024)
print(df.sort_values("value", ascending=False).head(10))

# Or as a list of dicts
rows = api.query(metric="employment_change_pct", geo_type="metro", year=2024, limit=10)
for row in rows:
    print(f"{row['name']}: {row['value']:+.1f}% job growth")

# Look up stats for a specific address
report = api.lookup("1600 Amphitheatre Pkwy, Mountain View, CA", auto_fetch=True)
print(f"Metro: {report.metro.name}{report.metro.metrics}")
print(f"City:  {report.city.name} — population {report.city.population:,}")
print(f"County: {report.county.name}")

# Configure (optional — works with defaults)
api.configure(db_path="my_data.db", min_population=100_000)

# Check what you have
api.status()
api.list_sources()
api.get_geographies(geo_type="metro", min_population=500_000)

CLI

# Fetch data
cityscope fetch census_population
cityscope fetch bls_employment --skip-laus
cityscope fetch --all

# Query
cityscope query -m population_change_pct -g metro -y 2024
cityscope query -m employment_change_pct -g metro -y 2024 -n 10
cityscope query -m avg_annual_pay -y 2024 -n 15

# Look up stats for an address
cityscope lookup "1600 Amphitheatre Pkwy, Mountain View, CA"
cityscope lookup "123 Main St, Austin, TX" --auto-fetch

# Info
cityscope sources
cityscope status

Commands

Command Description
fetch <source> Pull data from a source (census_population, bls_employment)
fetch --all Pull from all sources
query Query stored data (-m, -g, -y, --min-pop, -n)
lookup <address> Look up stats for a US address (metro + city + county)
sources List available data sources
status Show fetched data summary
init-config Generate default config/settings.yaml

Address Lookup

The lookup command geocodes a US address (via the free Census Geocoder) and returns stats for the enclosing metro, city, and county:

cityscope lookup "1600 Amphitheatre Pkwy, Mountain View, CA" --auto-fetch

With --auto-fetch, cityscope will fall back to fetching missing data from source APIs on-the-fly (useful for addresses in counties or smaller cities not covered by the default 200k+ metro/city fetch). Results are cached in the local DB.

Global flags: -v (verbose logging), -c PATH (custom config file).

Fetch Flags

Flag Description
--vintage YEAR Override Census vintage year
--min-pop N Override population filter (default: 200,000)
--skip-laus Skip unemployment rate (avoids BLS API daily limit)

What Data You Get

370+ metros and cities (200k+ population), each tracked across 9 metrics over 5 years (2020–2024):

Metric Source Description
population Census PEP/ACS Total population
population_change_pct Census PEP/ACS Year-over-year population growth %
employment BLS QCEW Total nonfarm jobs
employment_change_pct BLS QCEW Year-over-year job growth %
avg_annual_pay BLS QCEW Average annual pay ($)
avg_weekly_wage BLS QCEW Average weekly wage ($)
unemployment_rate BLS LAUS Annual avg unemployment rate (%)

All data is free, public domain, pulled directly from federal APIs.

Configuration

Optional — everything works with defaults. For higher API limits:

# config/settings.yaml
census:
  api_key: null    # Free: https://api.census.gov/data/key_signup.html
bls:
  api_key: null    # Free: https://data.bls.gov/registrationEngine/
storage:
  db_path: data/cityscope.db
pipeline:
  min_population: 200000

Or configure programmatically:

api.configure(census_api_key="your_key", bls_api_key="your_key")

Architecture

Census API ──┐                     ┌── Python API (cityscope.api)
             ├── Pipeline ── SQLite DB ──┤
BLS QCEW  ──┘    (fetch)          └── CLI (cityscope)

Data flows: Source → Pipeline → SQLite → API/CLI/your code.

Adding Data Sources

Each source is a self-contained class with @SourceRegistry.register:

from cityscope.core.registry import SourceRegistry
from cityscope.core.source import DataSource
from cityscope.core.models import FetchResult

@SourceRegistry.register
class MySource(DataSource):
    source_id = "my_source"
    name = "My Data Source"
    description = "What it provides"

    def fetch(self, **kwargs) -> FetchResult:
        ...

Add the import to src/cityscope/sources/__init__.py — it auto-registers in CLI, API, and pipeline.

Dashboard

For a visual dashboard, see urban-research-ui.

Roadmap

  • Rent data (HUD Fair Market Rents, Zillow ZORI)
  • Home price index (FHFA HPI)
  • Crime stats (FBI Crime Data Explorer)
  • School quality (NCES)
  • Walkability (EPA Smart Location Database)
  • Migration flows (IRS SOI county-to-county)
  • Neighborhood-level data (Census tract)
  • Composite scoring engine

See data_sources.md for research on 50+ public data sources.

Contributing

Pull requests welcome. The easiest way to contribute is adding a new data source — the plugin architecture makes it straightforward.

License

MIT


Built with Claude Code (Claude Opus 4.6).

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

cityscope-0.3.1.tar.gz (112.8 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

cityscope-0.3.1-py3-none-any.whl (35.6 kB view details)

Uploaded Python 3

File details

Details for the file cityscope-0.3.1.tar.gz.

File metadata

  • Download URL: cityscope-0.3.1.tar.gz
  • Upload date:
  • Size: 112.8 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for cityscope-0.3.1.tar.gz
Algorithm Hash digest
SHA256 be7d2c3e4fb26d2bc50c7c171404ef1bc3fb589910d839ad2c79027c3dd0aa76
MD5 2d36e1947baab56244f5d623785e8e53
BLAKE2b-256 5a6e4dcae86703be1a926c87ac14278b6491aa232a44e145c7f6bcc76f32676c

See more details on using hashes here.

Provenance

The following attestation bundles were made for cityscope-0.3.1.tar.gz:

Publisher: publish.yml on kkarbasi/cityscope

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file cityscope-0.3.1-py3-none-any.whl.

File metadata

  • Download URL: cityscope-0.3.1-py3-none-any.whl
  • Upload date:
  • Size: 35.6 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for cityscope-0.3.1-py3-none-any.whl
Algorithm Hash digest
SHA256 5d1ceabb11474802c73e28f4d48ecb6cb58b690e903d55d16ecfa080cca7ed51
MD5 b0f18d1512a64e3ab7d8748481991530
BLAKE2b-256 6cc6fa6c7d3f8b6a5b2b147b23f540f3a45396e5af4a6bd5ffc543f40908db67

See more details on using hashes here.

Provenance

The following attestation bundles were made for cityscope-0.3.1-py3-none-any.whl:

Publisher: publish.yml on kkarbasi/cityscope

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page