Metadata-Version: 2.4
Name: sf-appeal
Version: 0.1.6
Summary: SF Prop 8 Property Tax Appeal Tool — Analyze your property value against comparable sales and generate professional appeal reports.
License-Expression: MIT
Keywords: property-tax,appeal,proposition-8,san-francisco,real-estate,comparable-sales
Classifier: Development Status :: 4 - Beta
Classifier: Intended Audience :: End Users/Desktop
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.9
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Topic :: Office/Business :: Financial
Classifier: Topic :: Utilities
Classifier: Typing :: Typed
Requires-Python: >=3.9
Description-Content-Type: text/markdown
License-File: LICENSE
Requires-Dist: typer>=0.15.0
Requires-Dist: httpx>=0.28.0
Requires-Dist: pydantic>=2.0
Requires-Dist: rich>=13.0
Requires-Dist: redfin>=0.1
Requires-Dist: geopy>=2.4
Requires-Dist: python-dotenv>=1.0
Requires-Dist: jinja2>=3.1
Requires-Dist: weasyprint>=62.0
Provides-Extra: dev
Requires-Dist: pytest>=8.0; extra == "dev"
Requires-Dist: pytest-httpx>=0.35.0; extra == "dev"
Requires-Dist: ruff>=0.9.0; extra == "dev"
Dynamic: license-file

# sf-appeal

**SF Prop 8 Property Tax Appeal Tool** — Analyze your San Francisco property's assessed value against recent comparable sales and generate a professional appeal report.

Under California [Proposition 8](https://www.boe.ca.gov/proptaxes/faqs/decline-in-value.htm), if your property's current market value has declined below its assessed value, you can request a temporary reduction in your property tax assessment. This tool automates the comparable sales analysis that supports such an appeal.

## What It Does

1. **Looks up your property** from the SF Assessor's records (address, sqft, bedrooms, assessed value)
2. **Finds comparable recent sales** near your property using multiple data sources
3. **Applies adjustments** for differences in size, bedrooms, bathrooms, age, and lot size
4. **Calculates an estimated market value** using the median adjusted price per square foot
5. **Generates a PDF appeal report** with your comps, adjustment grid, written rationale, and filing instructions

## Installation

```bash
pip install sf-appeal
```

> **Note:** PDF generation requires [WeasyPrint](https://weasyprint.org/), which needs system libraries. On macOS: `brew install pango`. On Ubuntu/Debian: `apt install libpango-1.0-0 libpangocairo-1.0-0`.

### Optional: RentCast API Key

For additional comparable sales data beyond Redfin and DataSF, you can configure a [RentCast](https://www.rentcast.io/api) API key (50 free calls/month):

```bash
sf-appeal config
# or set the environment variable directly:
export RENTCAST_API_KEY=your_key_here
```

## Usage

### Interactive Mode

```bash
sf-appeal
```

Walks you through entering your address, choosing a search radius, reviewing your property details, and generating a report.

### Direct Commands

```bash
# Full analysis with PDF report (default)
sf-appeal report "123 Main St"

# Specify search radius and number of comps
sf-appeal report "123 Main St" --radius 1.0 --comps 5

# Markdown output instead of PDF
sf-appeal report "123 Main St" --format md

# Use a specific style seed (same seed = same visual style)
sf-appeal report "123 Main St" --seed myseed123

# Just look up property details
sf-appeal lookup "123 Main St"

# Just find comparable sales (no valuation)
sf-appeal comps "123 Main St" --radius 0.75

# Quick analysis without report file
sf-appeal analyze "123 Main St"

# Show filing deadlines and instructions
sf-appeal info
```

### Command Reference

| Command | Description |
|---------|-------------|
| `sf-appeal` | Interactive guided analysis |
| `sf-appeal analyze <address>` | Analyze property and show valuation |
| `sf-appeal lookup <address>` | Look up property details only |
| `sf-appeal comps <address>` | Find and display comparable sales |
| `sf-appeal report <address>` | Full analysis with PDF/Markdown report |
| `sf-appeal info` | Filing deadlines, forms, and instructions |
| `sf-appeal config` | Configure API keys |

### Report Options

| Option | Default | Description |
|--------|---------|-------------|
| `--radius` | `0.5` | Search radius in miles |
| `--months` | `12` | How far back to search for sales |
| `--comps` | `5` | Number of comps to select |
| `--format` / `-f` | `pdf` | Output format: `pdf` or `md` |
| `--seed` / `-s` | auto | Style randomization seed |
| `--output` / `-o` | auto | Output file path |

## How It Works

### Data Sources

- **SF Assessor (DataSF)** — Property details, assessed values, and characteristics via the [SF Open Data API](https://data.sfgov.org/Housing-and-Buildings/Assessor-Historical-Secured-Property-Tax-Rolls/wv5m-vpq2)
- **Redfin** — Recent comparable sales with sale prices, dates, and property details
- **RentCast** *(optional)* — Additional comparable sales data for broader coverage
- **Census Geocoder** — Address geocoding for distance calculations

### Comp Selection

Comparable sales are selected using a radiate-outward strategy:

1. Sales are grouped into distance rings from your property (0-0.25mi, 0.25-0.5mi, 0.5-1.0mi, etc.)
2. From each ring, the best statistical match with the lowest adjusted price is selected
3. Remaining slots are filled from the global pool, prioritizing the cheapest well-matched comps
4. Property types are matched: SFR with SFR, condo/TIC with condo/TIC, multi-family with multi-family

### Adjustments

Each comp is adjusted for differences from your property:

- **Size** (living area sqft) — scaled by price per sqft
- **Bedrooms** — +/- per bedroom difference
- **Bathrooms** — +/- per bathroom difference
- **Lot size** — proportional adjustment for SFRs
- **Building age** — per year of age difference

### Valuation

The **median** adjusted price per square foot across selected comps is used (more robust than mean against outliers). This is multiplied by your property's living area to estimate market value.

### PDF Styling

Each PDF report is generated with randomized formatting (fonts, colors, table styles, heading styles, spacing) so that no two reports look identical. A deterministic seed controls the randomization — the same seed always produces the same visual style. The default seed is based on your parcel number and the current date.

## Filing Your Appeal

### Informal Review (Free) — Deadline: March 31

1. Go to [online.sfassessor.org](https://online.sfassessor.org)
2. Select "Decline in Value"
3. Enter your parcel number and upload your report
4. Include the written rationale in the Comments field

### Formal Appeal ($120) — Deadline: September 15

1. File at [sfgov.org/aab](https://sfgov.org/aab/online-appeal-application)
2. Submit Application for Changed Assessment (BOE-305-AH)
3. Include your report as supporting evidence

## Development

```bash
git clone <your-repo-url>
cd appeal
python -m venv .venv
source .venv/bin/activate
pip install -e '.[dev]'
```

Run tests:

```bash
pytest
```

## License

[MIT](LICENSE)

## Disclaimer

This tool is for informational purposes only and does not constitute professional appraisal advice. Consult a licensed appraiser for a formal valuation. Tax laws and filing procedures may change — verify current deadlines with the [SF Assessor's Office](https://sfassessor.org).
