{"id":37083837,"url":"https://github.com/fxf8/noaa-cdo-api","last_synced_at":"2026-01-14T10:14:18.823Z","repository":{"id":285311473,"uuid":"957692597","full_name":"fxf8/noaa-cdo-api","owner":"fxf8","description":"A modern api wrapper for NOAA NCEI Web Services","archived":false,"fork":false,"pushed_at":"2025-04-27T02:48:26.000Z","size":1007,"stargazers_count":8,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2026-01-14T00:38:20.788Z","etag":null,"topics":["aiohttp-client","api-wrapper","async","asyncio","historical","modern","noaa","noaa-cdo","noaa-cdo-api","noaa-weather","python","typehints"],"latest_commit_sha":null,"homepage":"https://pypi.org/project/noaa-cdo-api/","language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/fxf8.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null}},"created_at":"2025-03-31T00:33:27.000Z","updated_at":"2025-10-17T17:51:46.000Z","dependencies_parsed_at":"2025-04-10T16:44:34.917Z","dependency_job_id":"8dbbadee-bd1f-4b9f-960d-f956faf6cccc","html_url":"https://github.com/fxf8/noaa-cdo-api","commit_stats":null,"previous_names":["fuexfollets/noaa-api","fxf8/noaa-cdo-api"],"tags_count":3,"template":false,"template_full_name":null,"purl":"pkg:github/fxf8/noaa-cdo-api","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/fxf8%2Fnoaa-cdo-api","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/fxf8%2Fnoaa-cdo-api/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/fxf8%2Fnoaa-cdo-api/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/fxf8%2Fnoaa-cdo-api/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/fxf8","download_url":"https://codeload.github.com/fxf8/noaa-cdo-api/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/fxf8%2Fnoaa-cdo-api/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":28416703,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-01-14T08:38:59.149Z","status":"ssl_error","status_checked_at":"2026-01-14T08:38:43.588Z","response_time":107,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.6:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["aiohttp-client","api-wrapper","async","asyncio","historical","modern","noaa","noaa-cdo","noaa-cdo-api","noaa-weather","python","typehints"],"created_at":"2026-01-14T10:14:18.251Z","updated_at":"2026-01-14T10:14:18.815Z","avatar_url":"https://github.com/fxf8.png","language":"Python","readme":"# NOAA Climate Data Online API Client\n\n\u003c!-- [![Python Version](https://img.shields.io/pypi/pyversions/noaa-cdo-api.svg)](https://pypi.org/project/noaa-cdo-api/) --\u003e\n[![PyPI version](https://badge.fury.io/py/noaa-cdo-api.svg)](https://badge.fury.io/py/noaa-cdo-api)\n[![GitHub Actions](https://github.com/fxf8/noaa-cdo-api/actions/workflows/lint.yml/badge.svg)](https://github.com/fxf8/noaa-cdo-api/actions)\n[![License](https://img.shields.io/github/license/fxf8/noaa-cdo-api.svg)](https://github.com/fxf8/noaa-cdo-api/blob/main/LICENSE)\n[![Documentation](https://img.shields.io/badge/docs-pdoc-blue)](https://fuexfollets.github.io/noaa-cdo-api)\n[![Ruff](https://img.shields.io/endpoint?url=https://raw.githubusercontent.com/astral-sh/ruff/main/assets/badge/v2.json)](https://github.com/astral-sh/ruff)\n[![uv](https://img.shields.io/endpoint?url=https://raw.githubusercontent.com/astral-sh/uv/main/assets/badge/v0.json)](https://github.com/astral-sh/uv)\n\u003c!-- [![Code style: black](https://img.shields.io/badge/code%20style-black-000000.svg)](https://github.com/psf/black) --\u003e\n\nAn asynchronous Python client for the NOAA National Centers for Environmental Information (NCEI) Climate Data Online (CDO) Web Services API v2. Features automatic rate limiting, connection pooling, and comprehensive type safety.\n\n## Features\n\n- ⚡ **Asynchronous API**: Built with `aiohttp` for high-performance async I/O\n- 🚦 **Automatic Rate Limiting**: Enforces NOAA's limits (5 req/sec, 10,000 req/day)\n- 🔄 **Connection Pooling**: Efficient TCP connection reuse\n- 📝 **Type Safety**: Full type hints and runtime validation\n- 🎨 **Beautiful Documentation**: Color-formatted docstrings with pdoc\n- 🛡️ **Resource Management**: Proper async context management\n- 📊 **Complete Coverage**: All documented NOAA CDO v2 endpoints supported\n\n## Installation\n\n```bash\npip install noaa-cdo-api\n```\n\n## API Documentation\n\nFull API documentation with colored formatting is available at [https://fxf8.github.io/noaa-cdo-api/](https://fxf8.github.io/noaa-cdo-api/).\n\n## Quick Start\n\n```python\nimport asyncio\nfrom noaa_cdo_api import NOAAClient, Extent\n\nasync def main():\n    # Best Practice: Use async context manager for automatic cleanup\n    async with NOAAClient(token=\"YOUR_TOKEN_HERE\") as client:\n        # Query available datasets\n        datasets = await client.get_datasets(limit=10)\n\n        # Query stations in a geographic region\n        stations = await client.get_stations(\n            extent=Extent(40.0, -80.0, 45.0, -75.0), # latitude_min, longitude_min, latitude_max, longitude_max\n            datasetid=\"GHCND\",\n            limit=5\n        )\n\n        # Get climate data with unit conversion\n        data = await client.get_data(\n            datasetid=\"GHCND\",\n            startdate=\"2022-01-01\",\n            enddate=\"2022-01-31\",\n            stationid=\"GHCND:USW00094728\",\n            units=\"metric\",\n            limit=100,\n        )\n\nif __name__ == \"__main__\":\n    asyncio.run(main())\n```\n\n## Important Implementation Notes\n\n### Event Loop Management\n```python\n# ❌ BAD: Creating multiple event loops\nclient1 = await NOAAClient(token=\"TOKEN1\")\nclient2 = await NOAAClient(token=\"TOKEN2\")\n\nresults = [*asyncio.run(client1.get_datasets(...)), *asyncio.run(client2.get_datasets(...))]\n\n# ✅ GOOD: Share the same event loop (note that rate limits apply **per token**)\nasync with NOAAClient(token=\"TOKEN1\") as client1, \\\n         NOAAClient(token=\"TOKEN2\") as client2:\n    await asyncio.gather(\n        client1.get_datasets(),\n        client2.get_datasets()\n    )\n```\n\n### Resource Management\n```python\n# ❌ Less ideal but functional: Manual cleanup\nclient = NOAAClient(token=\"TOKEN\")\ntry:\n    await client.get_datasets()\nfinally:\n    client.close()  # Might miss resources (note: close does not need to be awaited)\n\n# ✅ Better: Use async context manager\nasync with NOAAClient(token=\"TOKEN\") as client:\n    await client.get_datasets()\n```\n\n### Rate Limiting\n```python\n# ✅ Good: Use only a single client\nasync def parallel_with():\n    async with NOAAClient(token=\"TOKEN\") as client:\n        tasks = [client.get_datasets() for _ in range(20)]\n        return await asyncio.gather(*tasks)  # Rate limits respected\n\n\n# ❌ Bad: Each client has separate rate limits\nasync def parallel_separate():\n    tasks = []\n    for i in range(20):\n        client = NOAAClient(token=\"TOKEN\")  # Each has separate limiter\n        tasks.append(client.get_datasets())\n    return await asyncio.gather(*tasks)  # May exceed rate limits\n\n```\n\n## Tips\n\n1. **Connection Pooling**\n   - Reuse the same client instance\n   - Default connection limit is 10\n   - Adjust with `tcp_connector_limit` parameter\n\n2. **Pagination**\n   - Use `limit` and `offset` for large result sets\n   - Process data in chunks for memory efficiency\n\n3. **Data Volume**\n   - Limit date ranges (1 year for daily, 10 years for monthly)\n   - Use specific station IDs when possible\n   - Set `includemetadata=False` if not needed\n\n4. **Caching**\n   - Cache frequently accessed metadata\n   - Implement local caching for historical data\n\n\n### Available Endpoints\n\n- `/datasets`: Query available datasets\n- `/datacategories`: Query data categories\n- `/datatypes`: Query data types\n- `/locationcategories`: Query location categories\n- `/locations`: Query locations\n- `/stations`: Query weather stations\n- `/data`: Query actual climate data\n\n## Type Safety\n\nThe library provides comprehensive type checking through:\n- `TypedDict` schemas for all parameters\n- Runtime validation of parameter values\n- Proper enum types for constrained fields\n\nExample with type checking:\n```python\nfrom noaa_cdo_api import parameter_schemas\n\nparams: parameter_schemas.StationsParameters = {\n    \"extent\": \"42.0,-90.0,40.0,-88.0\",\n    \"datasetid\": \"GHCND\",\n    \"limit\": 100\n}\n```\n## License\n\nThis project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details.\n\n## Acknowledgments\n\n- NOAA's National Centers for Environmental Information (NCEI)\n- The aiohttp team for their excellent HTTP client\n- Contributors to the project\n\n## Getting Help\n\n- [Open an issue](https://github.com/fxf8/noaa-cdo-api/issues)\n- [Read the docs](https://fuexfollets.github.io/noaa-cdo-api)\n- [NOAA CDO API Documentation](https://www.ncdc.noaa.gov/cdo-web/webservices/v2)\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ffxf8%2Fnoaa-cdo-api","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Ffxf8%2Fnoaa-cdo-api","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ffxf8%2Fnoaa-cdo-api/lists"}