{"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,"search_vec":"'4.1.0':31 '404':57 '429':59 '500':6 'altern':69 'api':3,9,16,67,81,84 'automat':20 'break':39 'browser':52 'byte':7 'cadenc':33 'chang':40 'chrome':85,89 'convers':42 'core':92 'crux':2,8,79,80,82 'crux-api':1 'current':28 'definit':65 'differenti':50 'drop':45 'effectiveconnectiontyp':46 'esm':41 'experi':87 'fcp':97 'fetch':72 'handl':58,73 'histori':15,83 'irregular':34 'isomorph':51 'javascript':78 'key':49 'lack':75 'limit':24 'major':36 'manual':71 'node.js':53 'normal':27 'null':55 'perform':96 'provid':63 'rate':23 'record':13 'releas':32 'report':88,91 'requir':70 'respons':68 'retri':21,61 'return':54 'safeti':77 'stabl':29 'support':11 'tini':5 'type':19,76 'typescript':18,64 'url':26 'user':86 'ux':90 'v3':44 'v4':48 'version':30,37 'vital':94 'web':93,95 'wrapper':10","created_at":"2026-05-09T05:51:27.884387+00:00","updated_at":"2026-05-09T05:51:27.884387+00:00","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,"quickstart_score":null,"quickstart_tag":null,"pypi_latest":null,"cli_name":"","cli_version":null,"type":"library","homepage":null,"github":"https://github.com/treosh/crux-api","docs":null,"changelog":null,"pypi":null,"npm":"https://www.npmjs.com/package/crux-api","openapi_spec":null,"status_page":null,"smithery":null,"categories":["http-networking","observability"],"base_url":null,"auth_type":null,"provenance":{"verified_status":null,"verified_at":null,"last_verified":"2026-05-09","next_check":"2026-08-07","install_tag":null}}