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")

# 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

# 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)
sources List available data sources
status Show fetched data summary
init-config Generate default config/settings.yaml

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.2.0.tar.gz (80.5 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.2.0-py3-none-any.whl (22.0 kB view details)

Uploaded Python 3

File details

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

File metadata

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

File hashes

Hashes for cityscope-0.2.0.tar.gz
Algorithm Hash digest
SHA256 c80086aed99b7a3f5a854427a1414e14c5abb07c712da91203a77b7f3eaa2eb9
MD5 57005db3409e6e6b8ef69854fabf2fdd
BLAKE2b-256 fe238389ac1286b86eadaf3fdf1a8946d08e662a86411313231c5ba2b47c5c62

See more details on using hashes here.

Provenance

The following attestation bundles were made for cityscope-0.2.0.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.2.0-py3-none-any.whl.

File metadata

  • Download URL: cityscope-0.2.0-py3-none-any.whl
  • Upload date:
  • Size: 22.0 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.2.0-py3-none-any.whl
Algorithm Hash digest
SHA256 83e08150397affaf36bbc23a2b7564292b4d2ce4d0a0d62041ae2a1cb024c11a
MD5 2878e61bf1ed556c8335df3e118c4230
BLAKE2b-256 fafe2940a4a734ae335e6031162ea606fa78e38419232935f37c15b62a27344e

See more details on using hashes here.

Provenance

The following attestation bundles were made for cityscope-0.2.0-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