myhamilton311
A Python library for the MyHamilton 311 app API — the City of Hamilton, Ohio's citizen service request platform, backed by SeeClickFix.
Reverse-engineered from mitmproxy captures of the MyHamilton 311 iOS app (build 3884).
Installation
pip install requests # only runtime dependency
# or, from this repo:
pip install -e .
Quick Start
Unauthenticated — browse public issues
from myhamilton311 import MyHamilton311Client
client = MyHamilton311Client()
# Bounding box roughly covering Hamilton, OH
issues = client.get_issues(
min_lat=39.368, min_lng=-84.588,
max_lat=39.432, max_lng=-84.539,
)
print(f"{issues.pagination.entries} total issues found")
for issue in issues.issues:
print(f"[{issue.status}] #{issue.id} — {issue.summary}")
print(f" {issue.address}")
Authenticated — profile, my issues, city notices
from myhamilton311 import MyHamilton311Client, authenticate
# Opens a browser tab for CivicPlus / SeeClickFix login
token = authenticate()
client = MyHamilton311Client(access_token=token)
profile = client.get_profile()
print(f"Logged in as {profile.name} ({profile.email})")
for notice in client.get_notices_iter():
print(f"[{notice.published_at}] {notice.sender}: {notice.subject}")
If you already have a token (e.g. from a mitmproxy capture), supply it directly:
client = MyHamilton311Client(access_token="FvzaRk7i-HacbIx...")
API Reference
MyHamilton311Client
| Method | Auth required | Description |
|---|---|---|
get_mobile_app_config() |
No | Mobile app feature flags & branding |
get_scf_root() |
No | SCF platform root config |
get_mobile_strings() |
No | Localised UI strings |
get_closest_city(lat, lng) |
No | Nearest SeeClickFix place |
get_issues(min_lat, min_lng, max_lat, max_lng, …) |
No | Issues in bounding box |
get_issue(issue_id) |
No | Single issue by ID |
get_issues_page_iter(…) |
No | Generator over all pages |
get_bulletin_boards(lat, lng) |
No | City bulletin boards near point |
get_profile() |
Yes | Authenticated user's profile |
get_my_issues(…) |
Yes | Issues reported by current user |
get_notices(…) |
Yes | City / org notices |
get_notices_iter() |
Yes | Generator over all notice pages |
build_oauth_url(state, mode) |
— | Build OAuth authorization URL |
authenticate(mode, port, timeout)
Opens the system browser to complete the CivicPlus / SeeClickFix OAuth 2.0 implicit flow. Returns the Bearer access token string.
Protocol Notes
Reverse-engineered from 8 mitmproxy capture files covering:
- Initial app load —
GET /scf/v1/mobile_app_config,GET /api/v3/bulletin_boards - Browse issues —
GET /api/v2/issues?…bbox… - Registration — OAuth implicit flow → CivicPlus identity provider (IDS4) → OTP email verification → accept terms
- Sign out —
GET /oauth/logout→ CivicPlus backchannel logout - Sign in — Email-based lookup → CivicPlus password page → OAuth token
- Notices —
GET /api/v2/profile/notices - View issue (authenticated) —
GET /api/v2/issues/{id}?details=true - View issue (unauthenticated) — same endpoint, no Bearer token
Authentication flow
App → GET /oauth/authorize?client_id=zBmhzPX…&response_type=token&scf_login=choose
← 302 → /oauth/login
User enters email → POST /oauth/login
← 302 → /federated_logins/ids4/1118?email=… (CivicPlus IDP)
CivicPlus handles password entry → POST /federated_logins/ids4/callback (code + id_token JWT)
← 302 → /oauth/authorize (SCF exchanges code for token)
← 302 → com.citysourced.hamiltonoh://oauth/callback#access_token=<BEARER_TOKEN>
Key constants
| Constant | Value |
|---|---|
| Base URL | https://seeclickfix.com |
| OAuth Client ID | zBmhzPXICuENMfUUhjX2nzvvADnCnuKxLxVPmsk4s_c |
| OAuth Redirect URI | com.citysourced.hamiltonoh://oauth/callback |
| Hamilton Place ID | 16830 |
| Hamilton Org ID | 1118 |
| CivicPlus IDP | https://cpauthentication.civicplus.com |
| iOS User-Agent | MyHamilton%20311/3884 CFNetwork/3860.600.21 Darwin/25.5.0 |
Legal
This library is for research and personal use only. The SeeClickFix API is proprietary. Be respectful of rate limits and do not use this library for scraping at scale.
Metadata
Release files for myhamilton311 0.2.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| myhamilton311-0.2.0.tar.gz | 16.0 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| myhamilton311-0.2.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 32.0 kB
Release files / myhamilton311-0.2.0.tar.gz
| Download URL | myhamilton311-0.2.0.tar.gz |
|---|---|
| Size | 16.0 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
c49adb1983e3447045f8d3f023801517772136dd9ae45dd0246407bd0a2f1c7d
|
|
BLAKE2b-256 checksum How to use checksums |
e37d212c30644acaa0f88ba6c284f8a39dfcb7d10f20fc8f9f269a768512cbed
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/6.1.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Jul 20, 2026.
Transparency logRelease files / myhamilton311-0.2.0-py3-none-any.whl
| Download URL | myhamilton311-0.2.0-py3-none-any.whl |
|---|---|
| Size | 16.0 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
9084e9e33036867436c4aa8735be0f3344fe0a1cd49bd187c46166d41aa77f16
|
|
BLAKE2b-256 checksum How to use checksums |
32cd8dacfb0fe0ec87338a00cff91aa359d83de0b16195e7b4f9104fe5e73eb9
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/6.1.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Jul 20, 2026.
Transparency log