{"id":30900634,"url":"https://github.com/ejfox/openrouter-census","last_synced_at":"2025-09-09T05:53:20.985Z","repository":{"id":312343848,"uuid":"1042262017","full_name":"ejfox/openrouter-census","owner":"ejfox","description":"🤖 Complete analysis of 316+ AI models on OpenRouter with interactive Observable Plot dashboard","archived":false,"fork":false,"pushed_at":"2025-08-21T18:25:21.000Z","size":135,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2025-09-06T18:00:17.847Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/ejfox.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"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,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2025-08-21T18:25:17.000Z","updated_at":"2025-08-21T18:25:25.000Z","dependencies_parsed_at":"2025-08-30T00:53:16.618Z","dependency_job_id":"551b72e1-a582-48e4-8f95-d06af8679bfb","html_url":"https://github.com/ejfox/openrouter-census","commit_stats":null,"previous_names":["ejfox/openrouter-census"],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/ejfox/openrouter-census","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ejfox%2Fopenrouter-census","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ejfox%2Fopenrouter-census/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ejfox%2Fopenrouter-census/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ejfox%2Fopenrouter-census/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/ejfox","download_url":"https://codeload.github.com/ejfox/openrouter-census/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ejfox%2Fopenrouter-census/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":274250508,"owners_count":25249396,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","status":"online","status_checked_at":"2025-09-09T02:00:10.223Z","response_time":80,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"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":[],"created_at":"2025-09-09T05:53:19.345Z","updated_at":"2025-09-09T05:53:20.957Z","avatar_url":"https://github.com/ejfox.png","language":"JavaScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# 🤖 OpenRouter Model Census\n\nA complete analysis tool for **all 316+ AI models** on OpenRouter—featuring fast scraping, Python-style data analysis, and beautiful Observable Plot visualizations. Get pricing insights, provider comparisons, and model capabilities in an interactive dashboard.\n\n![Dashboard Preview](https://img.shields.io/badge/Charts-7%20Interactive-blue) ![Models](https://img.shields.io/badge/Models-316+-green) ![Providers](https://img.shields.io/badge/Providers-54+-orange)\n\n---\n\n## 🚀 Quick Start\n\n```bash\n# Clone and install\ngit clone https://github.com/your-username/openrouter-scrape\ncd openrouter-scrape\nnpm install\n\n# Run complete pipeline (scrape + analyze + serve dashboard)\nnpm run full-pipeline\n```\n\n**That's it!** Your dashboard opens at `http://localhost:8080` with fresh data on all 316+ models.\n\n## ✨ Features\n\n* **⚡ Fast scraping** - All 316 models in under 1 second\n* **📊 Beautiful charts** - 7 interactive Observable Plot visualizations  \n* **💰 Pricing insights** - Find the cheapest models, price vs context analysis\n* **🏢 Provider analysis** - Market share, strategy mapping, capabilities\n* **📱 Responsive design** - Works great on mobile and desktop\n* **🔄 Easy updates** - Re-run anytime for fresh data\n\n---\n\n## What gets collected\n\n### Layer 1 — Models (`GET /api/v1/models`)\n\n* Identity: `id`, `name`, `canonical_slug`, `created`, `description`\n* Architecture: `input_modalities`, `output_modalities`, `tokenizer`, `instruct_type`\n* Aggregates: `context_length` (model-wide), `supported_parameters` (**union across providers**)\n* Pricing (as published): `prompt`, `completion`, `request`, `image`, `web_search`, `internal_reasoning`, `input_cache_read`, `input_cache_write`\n* Top provider summary: `context_length`, `max_completion_tokens`, `is_moderated`\n  Notes: `supported_parameters` at model level is a **union**, not guaranteed at any single endpoint. ([OpenRouter][2])\n\n### Layer 2 — Provider Endpoints (`GET /api/v1/models/:author/:slug/endpoints`)\n\nPer provider that hosts the model:\n\n* `provider_name`, `name` (endpoint), `status`, `uptime_last_30m`\n* Limits: `context_length`, `max_prompt_tokens`, `max_completion_tokens`, `quantization`\n* Capabilities: endpoint-level `supported_parameters`\n* Pricing overrides: `prompt`, `completion`, `request`, `image`\n  Use these to resolve real availability and price for your route. ([OpenRouter][4])\n\n### Layer 3 — Optional Generation Telemetry (`GET /api/v1/generation` or inline **usage accounting**)\n\nIf you have generation IDs or enable usage accounting in your workloads:\n\n* Identity \u0026 routing: `model`, `provider_name`, `origin`, `upstream_id`\n* Tokens (native): `native_tokens_prompt`, `native_tokens_completion`, `native_tokens_reasoning`\n* Tokens (gateway): `tokens_prompt`, `tokens_completion`\n* Cost: `total_cost`, `cache_discount`, `upstream_inference_cost`\n* Timings: `latency`, `generation_time`, moderation latency\n* Termination: `finish_reason`, `native_finish_reason`\n* Media/search counters; cached token counts (reads)\n  This enables empirical latency/cost analyses grounded in the provider’s native tokenizer. ([OpenRouter][3])\n\n---\n\n## Outputs (immutable, analysis-ready)\n\n* `artifacts/YYYY-MM-DD/`\n\n  * `models.jsonl` (one model per line; raw API objects)\n  * `endpoints.jsonl` (provider-expanded rows)\n  * `joined.parquet` (denormalized: model ⨯ endpoint)\n  * `telemetry.jsonl` (optional generation/usage rows)\n  * `schema/*.json` (JSON Schema for each file)\n  * `MANIFEST.sha256` (file → SHA-256)\n  * `FETCH_METADATA.json` (request URLs, headers, etags, timestamps, versions)\n  * `CITATION.cff` (how to cite this snapshot)\n  * `NOTICE.txt` (license + terms provenance)\n* All files compressed with `zstd` if `--zstd` is set.\n\n---\n\n## Install\n\n```bash\n# Node 20+ recommended\npnpm i -g openrouter-census   # or: npx openrouter-census\n```\n\nLocal dev:\n\n```bash\ngit clone https://github.com/yourorg/openrouter-census\ncd openrouter-census\npnpm install\n```\n\n---\n\n## Configuration\n\n```bash\n# Optional: required only if you fetch protected usage for your own generations\nexport OPENROUTER_API_KEY=... \n\n# Rate limits (Bottleneck): default is conservative; override as needed\nexport CENSUS_RESERVOIR=100        # max requests per window\nexport CENSUS_INTERVAL_MS=60_000   # window length\nexport CENSUS_MAX_CONCURRENCY=8    # parallelism\n```\n\n\u003e Tip: tune Bottleneck’s **reservoir** + **interval** for burst/steady control. Keep headroom for Cloudflare/DDOS protections and any per-account limits. ([OpenRouter][5], [DEV Community][6])\n\n---\n\n## Usage (CLI \u0026 TUI)\n\n```bash\nopenrouter-census tui\n```\n\n**TUI features**\n\n* Live counters: queued / inflight / completed / failed\n* Throttles: adjust concurrency \u0026 reservoir at runtime\n* Filters: by provider, family, modality, supports(param)\n* Export panel: write JSONL/Parquet + schemas + manifest\n* Retry controls: backoff/rehydrate failed requests\n\n**Non-interactive**\n\n```bash\n# Full scrape → immutable snapshot directory\nopenrouter-census run --out artifacts/$(date +%F) --zstd\n\n# Fetch with telemetry (ids from stdin) and merge\ncat ids.txt | openrouter-census usage --append artifacts/2025-08-21/telemetry.jsonl\n```\n\n---\n\n## Data model (schemas)\n\n* `schema/models.schema.json` – exact API fields from `/models` with permissive `additionalProperties: true`\n* `schema/endpoints.schema.json` – rows keyed by `(model_id, provider_name, endpoint_name)`\n* `schema/telemetry.schema.json` – union of `/generation` + inline usage accounting fields\n* `schema/joined.schema.json` – normalized and namespaced (`model.*`, `endpoint.*`, `price.*`, `limits.*`)\n\nSchemas are versioned; each run stores the **exact** schema copy used to validate outputs.\n\n---\n\n## Reproducibility \u0026 provenance\n\n* **Deterministic traversal:** stable sort of model IDs; endpoint requests queued in lexical order.\n* **Version pins:** `pnpm-lock.yaml` checked in; run logs emit Node + package versions.\n* **Raw preservation:** we persist **unmodified** API payloads alongside normalized tables.\n* **Integrity:** SHA-256 digests and `FETCH_METADATA.json` (timestamps, etags, cache status).\n* **Citations:** `CITATION.cff` includes title, version, DOI placeholder, and snapshot date.\n* **License/Terms capture:** `NOTICE.txt` records the doc URLs and access dates for API docs.\n\n---\n\n## Limits, caveats, ethics\n\n* `supported_parameters` at model level is **union**; intersect with endpoint capabilities for truth in UX or routing guarantees. ([OpenRouter][1])\n* Endpoint `uptime_last_30m` is a short pulse, not an SLA. Prefer aggregates if you collect telemetry. ([OpenRouter][4])\n* Pricing may differ per endpoint; do not assume model-level pricing applies to your chosen provider. ([OpenRouter][4])\n* Respect rate limits \u0026 terms; don’t stress shared free endpoints. Consider backoffs and caching. ([OpenRouter][5])\n\n---\n\n## Programmatic API (library usage)\n\n```ts\nimport { census } from \"openrouter-census\";\n\nconst run = await census({\n  outDir: \"artifacts/2025-08-21\",\n  concurrency: 8,\n  reservoir: 100,\n  intervalMs: 60_000,\n  fetchTelemetry: false,\n});\nconsole.log(run.summary);\n```\n\n---\n\n## Minimal pipeline spec\n\n1. **Models pass**\n\n   * GET `https://openrouter.ai/api/v1/models` → write raw → validate → extract rows. ([OpenRouter][2])\n2. **Endpoints pass**\n\n   * For each `{author}/{slug}`, GET `/api/v1/models/:author/:slug/endpoints` → write raw → validate → rows. ([OpenRouter][4])\n3. **(Optional) Telemetry pass**\n\n   * For provided generation IDs or inline usage payloads, normalize and append to `telemetry.jsonl`. ([OpenRouter][3])\n4. **Join \u0026 export**\n\n   * Create `joined.parquet` + schemas + manifest + checksums.\n\n---\n\n## What you can visualize later (suggestions)\n\n* **Price vs context** (per endpoint)\n* **Parameter support heatmap** (models × params; intersected, not union)\n* **Short-window reliability** (endpoint uptime)\n* **Observed latency \u0026 effective \\$/1k** from telemetry (native tokens)\n\n---\n\n## References\n\n* Models API \u0026 schema. ([OpenRouter][2])\n* List models (union of `supported_parameters`). ([OpenRouter][1])\n* Per-model endpoints (provider-specific limits/pricing/uptime). ([OpenRouter][4])\n* Usage accounting (native tokens, cached tokens, reasoning tokens). ([OpenRouter][7])\n* Precise token accounting \u0026 `/generation`. ([OpenRouter][3])\n* Reasoning tokens overview. ([OpenRouter][8])\n* OpenRouter limits (guidance for throttling). ([OpenRouter][5])\n* Bottleneck patterns for Node rate limiting. ([DEV Community][6])\n\n---\n\n## License\n\nMIT for code. Data artifacts inherit upstream terms; see `NOTICE.txt`.\n\n[1]: https://openrouter.ai/docs/api-reference/list-available-models?utm_source=chatgpt.com \"List available models | OpenRouter | Documentation\"\n[2]: https://openrouter.ai/docs/models?utm_source=chatgpt.com \"Access 400+ AI Models Through One API - OpenRouter\"\n[3]: https://openrouter.ai/docs/api-reference/overview?utm_source=chatgpt.com \"OpenRouter API Reference | Complete API Documentation\"\n[4]: https://openrouter.ai/docs/api-reference/list-endpoints-for-a-model?utm_source=chatgpt.com \"List endpoints for a model | OpenRouter | Documentation\"\n[5]: https://openrouter.ai/docs/api-reference/limits?utm_source=chatgpt.com \"API Rate Limits | Configure Usage Limits in OpenRouter\"\n[6]: https://dev.to/arifszn/prevent-api-overload-a-comprehensive-guide-to-rate-limiting-with-bottleneck-c2p?utm_source=chatgpt.com \"Prevent API Overload: A Comprehensive Guide to Rate Limiting with ...\"\n[7]: https://openrouter.ai/docs/use-cases/usage-accounting?utm_source=chatgpt.com \"Usage Accounting | Track AI Model Usage with OpenRouter\"\n[8]: https://openrouter.ai/docs/use-cases/reasoning-tokens?utm_source=chatgpt.com \"Reasoning Tokens | Enhanced AI Model Reasoning with OpenRouter\"\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fejfox%2Fopenrouter-census","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fejfox%2Fopenrouter-census","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fejfox%2Fopenrouter-census/lists"}