{"id":27669,"library":"crux-api","title":"crux-api","description":"A tiny (~500 bytes) CrUX API wrapper supporting both record and history APIs, with TypeScript types, automatic retry on rate limits, and URL normalization. Current stable version: 4.1.0. Release cadence: irregular, with major versions for breaking changes (ESM conversion in v3, dropping effectiveConnectionType in v4). Key differentiators: isomorphic (browser + Node.js), returns null on 404, handles 429 with retries, and provides TypeScript definitions for API responses. Alternatives require manual fetch handling and lack type safety.","status":"active","version":"4.1.0","language":"javascript","source_language":"en","source_url":"https://github.com/treosh/crux-api","tags":["javascript","CrUX","CrUX API","CrUX History API","Chrome User Experience Report","Chrome UX Report","Core Web Vitals","Web Performance","FCP"],"install":[{"cmd":"npm install crux-api","lang":"bash","label":"npm"},{"cmd":"yarn add crux-api","lang":"bash","label":"yarn"},{"cmd":"pnpm add crux-api","lang":"bash","label":"pnpm"}],"dependencies":[],"imports":[{"note":"ESM-only since v3. CommonJS require is not supported.","wrong":"const { createQueryRecord } = require('crux-api')","symbol":"createQueryRecord","correct":"import { createQueryRecord } from 'crux-api'"},{"note":"Named export, not default. Use named import.","wrong":"import createQueryHistoryRecord from 'crux-api'","symbol":"createQueryHistoryRecord","correct":"import { createQueryHistoryRecord } from 'crux-api'"},{"note":"Helper to normalize URLs for CrUX API indexing.","wrong":"","symbol":"normalizeUrl","correct":"import { normalizeUrl } from 'crux-api'"}],"quickstart":{"code":"import { createQueryRecord, createQueryHistoryRecord } from 'crux-api'\n\nconst CRUX_API_KEY = process.env.CRUX_API_KEY ?? ''\n\nconst queryRecord = createQueryRecord({ key: CRUX_API_KEY })\nconst queryHistory = createQueryHistoryRecord({ key: CRUX_API_KEY })\n\nasync function main() {\n  // Fetch record data\n  const record = await queryRecord({ url: 'https://example.com' })\n  console.log('Record:', record)\n\n  // Fetch history data\n  const history = await queryHistory({ url: 'https://example.com' })\n  console.log('History:', history)\n\n  // Normalize a URL\n  const normalized = normalizeUrl('https://example.com/path?query=1#hash')\n  console.log('Normalized:', normalized)\n}\n\nmain().catch(console.error)","lang":"typescript","description":"Creates queryRecord and queryHistoryRecord instances with an API key, fetches CrUX data for a URL, and normalizes URLs."},"warnings":[{"fix":"Remove effectiveConnectionType parameter from queries; it is no longer supported by CrUX API.","message":"v4.0.0 drops effectiveConnectionType support (deprecated by CrUX API). If you rely on connectivity data, you must remove related code.","severity":"breaking","affected_versions":">=4.0.0"},{"fix":"Use ES module imports (import { createQueryRecord } from 'crux-api') or switch to dynamic import.","message":"v3.0.0 converts the package to ES module. require() will not work; you must use import syntax.","severity":"breaking","affected_versions":">=3.0.0"},{"fix":"Use individual queryRecord calls for each URL instead of batch.","message":"v2.0.0 drops the batch API. Code using batchQueryRecord will break.","severity":"breaking","affected_versions":">=2.0.0"},{"fix":"Pass a valid key to createQueryRecord or createQueryHistoryRecord.","message":"The API key (CRUX_API_KEY) is required. If not provided, requests will fail with a 403 error.","severity":"gotcha","affected_versions":">=1.0.0"},{"fix":"Always check for null return before accessing properties.","message":"When URL is not found in CrUX data, the library returns null (not an error). This can silently skip missing data if not checked.","severity":"gotcha","affected_versions":">=1.0.0"}],"env_vars":null,"last_verified":"2026-05-09T00:00:00.000Z","next_check":"2026-08-07T00:00:00.000Z","problems":[{"fix":"Use named import: import { createQueryRecord } from 'crux-api'","cause":"Importing the default export instead of named export, or using CommonJS with ESM-only library (v3+).","error":"TypeError: createQueryRecord is not a function"},{"fix":"Wait for quota reset or reduce request frequency. The library retries automatically on 429, but if retries are exhausted, you may need to upgrade your API plan.","cause":"Exceeded CrUX API daily quota or rate limit.","error":"Error: Quota exceeded (429)"},{"fix":"The library returns null for 404; handle null gracefully. Ensure URL is normalized (use normalizeUrl).","cause":"The requested URL is not in CrUX data or is invalid.","error":"Error: Not Found (404)"},{"fix":"Use import syntax or dynamic import(): const mod = await import('crux-api')","cause":"Using require() on a package that is ESM-only (v3+).","error":"Error [ERR_REQUIRE_ESM]: require() of ES Module not supported"}],"ecosystem":"npm","meta_description":null,"install_score":null,"install_tag":null,"quickstart_score":null,"quickstart_tag":null}