{"id":17963943,"url":"https://github.com/kamiazya/web-csv-toolbox","last_synced_at":"2025-12-25T03:17:13.446Z","repository":{"id":213532484,"uuid":"722353195","full_name":"kamiazya/web-csv-toolbox","owner":"kamiazya","description":"🌊A CSV Toolbox utilizing Web Standard APIs.","archived":false,"fork":false,"pushed_at":"2025-12-06T08:43:34.000Z","size":3633,"stargazers_count":19,"open_issues_count":40,"forks_count":11,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-12-08T00:54:57.890Z","etag":null,"topics":["csv","hacktoberfest","web-streams"],"latest_commit_sha":null,"homepage":"https://kamiazya.github.io/web-csv-toolbox/","language":"TypeScript","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/kamiazya.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":"CODE_OF_CONDUCT.md","threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":"SECURITY.md","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},"funding":{"github":"kamiazya","patreon":null,"open_collective":"kamiazya","ko_fi":"kamiazya","tidelift":null,"community_bridge":null,"liberapay":null,"issuehunt":null,"otechie":null,"custom":null}},"created_at":"2023-11-23T00:53:52.000Z","updated_at":"2025-12-06T08:34:57.000Z","dependencies_parsed_at":"2024-03-27T07:32:58.639Z","dependency_job_id":"132c2a39-7ff1-4efa-bca9-8518cbafbc96","html_url":"https://github.com/kamiazya/web-csv-toolbox","commit_stats":null,"previous_names":["kamiazya/web-streams-csv","kamiazya/web-csv-toolbox"],"tags_count":19,"template":false,"template_full_name":null,"purl":"pkg:github/kamiazya/web-csv-toolbox","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/kamiazya%2Fweb-csv-toolbox","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/kamiazya%2Fweb-csv-toolbox/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/kamiazya%2Fweb-csv-toolbox/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/kamiazya%2Fweb-csv-toolbox/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/kamiazya","download_url":"https://codeload.github.com/kamiazya/web-csv-toolbox/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/kamiazya%2Fweb-csv-toolbox/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":28017921,"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-12-25T02:00:05.988Z","response_time":58,"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":["csv","hacktoberfest","web-streams"],"created_at":"2024-10-29T11:45:56.677Z","updated_at":"2025-12-25T03:17:13.432Z","avatar_url":"https://github.com/kamiazya.png","language":"TypeScript","funding_links":["https://github.com/sponsors/kamiazya","https://opencollective.com/kamiazya","https://ko-fi.com/kamiazya"],"categories":[],"sub_categories":[],"readme":"\u003cdiv align=\"center\"\u003e\n\n[![npm version](https://badge.fury.io/js/web-csv-toolbox.svg)](https://badge.fury.io/js/web-csv-toolbox)\n[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)\n[![PRs Welcome](https://img.shields.io/badge/PRs-welcome-brightgreen.svg)](http://makeapullrequest.com)\n![node version](https://img.shields.io/node/v/web-csv-toolbox)\n[![FOSSA Status](https://app.fossa.com/api/projects/git%2Bgithub.com%2Fkamiazya%2Fweb-csv-toolbox.svg?type=shield)](https://app.fossa.com/projects/git%2Bgithub.com%2Fkamiazya%2Fweb-csv-toolbox?ref=badge_shield)\n\n![GitHub code size in bytes](https://img.shields.io/github/languages/code-size/kamiazya/web-csv-toolbox)\n![npm](https://img.shields.io/npm/dm/web-csv-toolbox)\n[![codecov](https://codecov.io/gh/kamiazya/web-csv-toolbox/graph/badge.svg?token=8RbDcXHTFl)](https://codecov.io/gh/kamiazya/web-csv-toolbox)\n\n# `🌐 web-csv-toolbox 🧰`\n\nA CSV Toolbox utilizing Web Standard APIs.\n\n🔗\n\n[![GitHub](https://img.shields.io/badge/-GitHub-181717?logo=GitHub\u0026style=flat)](https://github.com/kamiazya/web-csv-toolbox)\n[![npm](https://img.shields.io/badge/-npm-CB3837?logo=npm\u0026style=flat)](https://www.npmjs.com/package/web-csv-toolbox)\n[![API Reference](https://img.shields.io/badge/-API%20Reference-3178C6?logo=TypeScript\u0026style=flat\u0026logoColor=fff)](https://kamiazya.github.io/web-csv-toolbox/)\n[![Ask DeepWiki](https://deepwiki.com/badge.svg)](https://deepwiki.com/kamiazya/web-csv-toolbox)\n[![Sponsor](https://img.shields.io/badge/-GitHub%20Sponsor-fff?logo=GitHub%20Sponsors\u0026style=flat)](https://github.com/sponsors/kamiazya)\n[![CodSpeed Badge](https://img.shields.io/endpoint?url=https://codspeed.io/badge.json)](https://codspeed.io/kamiazya/web-csv-toolbox)\n\n[![format: Biome](https://img.shields.io/badge/format%20with-Biome-F7B911?logo=biome\u0026style=flat)](https://biomejs.dev/)\n[![test: Vitest](https://img.shields.io/badge/tested%20with-Vitest-6E9F18?logo=vitest\u0026style=flat)](https://vitest.dev/)\n[![build: Vite](https://img.shields.io/badge/build%20with-Vite-646CFF?logo=vite\u0026style=flat)](https://rollupjs.org/)\n\n\u003ca href=\"https://flatt.tech/oss/gmo/trampoline\" target=\"_blank\"\u003e\u003cimg src=\"https://flatt.tech/assets/images/badges/gmo-oss.svg\" height=\"24px\" alt=\"GMO OSS support\"/\u003e\u003c/a\u003e\n\n\u003c/div\u003e\n\n---\n\n## Key Concepts ✨\n\n- 🌐 **Web Standards first.**\n  - Utilizing the Web Standards APIs, such as the [Web Streams API](https://developer.mozilla.org/en/docs/Web/API/Streams_API).\n- ❤️ **TypeScript friendly \u0026 User friendly.**\n  - Fully typed and documented.\n- 0️⃣ **Zero dependencies.**\n  - Using only Web Standards APIs.\n- 💪 **Property-based testing.**\n  - Using [fast-check](https://fast-check.dev/) and [vitest](https://vitest.dev).\n- ✅ **Cross-platform.**\n  - Works on browsers, Node.js, and Deno.\n\n## Key Features 📗\n\n- 🌊 **Efficient CSV Parsing with Streams**\n  - 💻 Leveraging the [WHATWG Streams API](https://streams.spec.whatwg.org/) and other Web APIs for seamless and efficient data processing.\n- 🛑 **AbortSignal and Timeout Support**: Ensure your CSV processing is cancellable, including support for automatic timeouts.\n  - ✋ Integrate with [`AbortController`](https://developer.mozilla.org/docs/Web/API/AbortController) to manually cancel operations as needed.\n  - ⏳ Use [`AbortSignal.timeout`](https://developer.mozilla.org/docs/Web/API/AbortSignal/timeout_static) to automatically cancel operations that exceed a specified time limit.\n- 🛡️ **Memory Safety Protection**: Built-in limits prevent memory exhaustion attacks.\n  - 🔒 Configurable maximum buffer size (default: 10M characters) to prevent DoS attacks via unbounded input.\n    - 🚨 Throws `RangeError` when buffer exceeds the limit.\n  - 📊 Configurable maximum field count (default: 100,000 fields/record) to prevent excessive column attacks.\n    - ⚠️ Throws `RangeError` when field count exceeds the limit.\n  - 💾 Configurable maximum binary size (default: 100MB bytes) for BufferSource inputs.\n    - 🛑 Throws `RangeError` when binary size exceeds the limit.\n- 🎨 **Flexible Source Support**\n  - 🧩 Parse CSVs directly from `string`s, `ReadableStream`s, `Response` objects, `Blob`/`File` objects, or `Request` objects.\n- ⚙️ **Advanced Parsing Options**: Customize your experience with various delimiters and quotation marks.\n  - 🔄 Defaults to `,` and `\"` respectively.\n- 💾 **Specialized Binary CSV Parsing**: Leverage Stream-based processing for versatility and strength.\n  - 🔄 Flexible BOM handling.\n  - 🗜️ Supports various compression formats.\n  - 🔤 Charset specification for diverse encoding.\n- 🚀 **Using WebAssembly for High Performance**: WebAssembly is used for high performance parsing. (_Experimental_)\n  - 📦 WebAssembly is used for high performance parsing.\n  - ⚠️ **Experimental**: WASM automatic initialization (base64-embedded) is experimental and may change in future versions.\n- 📦 **Lightweight and Zero Dependencies**: No external dependencies, only Web Standards APIs.\n- 📚 **Fully Typed and Documented**: Fully typed and documented with [TypeDoc](https://typedoc.org/).\n\n## Installation 📥\n\n### With Package manager 📦\n\nThis package can then be installed using a package manager.\n\n```sh\n# Install with npm\n$ npm install web-csv-toolbox\n# Or Yarn\n$ yarn add web-csv-toolbox\n# Or pnpm\n$ pnpm add web-csv-toolbox\n```\n\n### From CDN (unpkg.com) 🌐\n\n```html\n\u003cscript type=\"module\"\u003e\nimport { parse } from 'https://unpkg.com/web-csv-toolbox';\n\nconst csv = `name,age\nAlice,42\nBob,69`;\n\nfor await (const record of parse(csv)) {\n  console.log(record);\n}\n\u003c/script\u003e\n```\n\n#### Deno 🦕\n\nYou can install and use the package by specifying the following:\n\n```js\nimport { parse } from \"npm:web-csv-toolbox\";\n```\n\n## Entry Points 🚪\n\nThis library provides two entry points to suit different needs:\n\nFor a deeper comparison and migration guidance, see:\n\n- docs/explanation/main-vs-slim.md\n\n### `web-csv-toolbox` (Default - Full Features)\n\n**Best for**: Most users who want automatic WASM initialization and all features\n\n```typescript\nimport { loadWASM, parseStringToArraySyncWASM } from 'web-csv-toolbox';\n\n// Optional but recommended: preload to reduce first‑parse latency\nawait loadWASM();\nconst records = parseStringToArraySyncWASM(csv);\n```\n\n**Characteristics:**\n- ✅ Full features including synchronous WASM APIs\n- ✅ Automatic WASM initialization on first use (not at import time)\n- 💡 Call `loadWASM()` at startup to reduce first‑parse latency (optional)\n- ⚠️ **Experimental**: WASM auto-init embeds WASM as base64, may change in future\n- ⚠️ Larger bundle size (WASM embedded in main bundle)\n\n### `web-csv-toolbox/slim` (Slim Entry - Smaller Bundle)\n\n**Best for**: Bundle size-sensitive applications and production optimization\n\n```typescript\nimport { loadWASM, parseStringToArraySyncWASM } from 'web-csv-toolbox/slim';\n\n// Manual initialization required\nawait loadWASM();\nconst records = parseStringToArraySyncWASM(csv);\n```\n\n**Characteristics:**\n- ✅ Smaller main bundle (WASM not embedded)\n- ✅ External WASM loading for better caching\n- ✅ Explicit control over initialization timing\n- ❌ Requires manual `loadWASM()` call before using WASM features\n\n**Comparison:**\n\n| Aspect | Main | Slim |\n|--------|------|------|\n| **Initialization** | Automatic | Manual (`loadWASM()` required) |\n| **Bundle Size** | Larger (WASM embedded) | Smaller (WASM external) |\n| **Caching** | Single bundle | WASM cached separately |\n| **Use Case** | Convenience, prototyping | Production, bundle optimization |\n\n\u003e **Note**: Both entry points export the same full API (feature parity). The only difference is WASM initialization strategy and bundle size.\n\n## Usage 📘\n\n\u003e **Note for Bundler Users**: When using Worker-based execution strategies (e.g., `EnginePresets.responsive()`, `EnginePresets.responsiveFast()`) with bundlers like Vite or Webpack, you must explicitly specify the `workerURL` option. See the [Bundler Integration Guide](./docs/how-to-guides/using-with-bundlers.md) for configuration details.\n\n### Parsing CSV files from strings\n\n```js\nimport { parse } from 'web-csv-toolbox';\n\nconst csv = `name,age\nAlice,42\nBob,69`;\n\nfor await (const record of parse(csv)) {\n  console.log(record);\n}\n// Prints:\n// { name: 'Alice', age: '42' }\n// { name: 'Bob', age: '69' }\n```\n\n### Parsing CSV files from `ReadableStream`s\n\n```js\nimport { parse } from 'web-csv-toolbox';\n\nconst csv = `name,age\nAlice,42\nBob,69`;\n\nconst stream = new ReadableStream({\n  start(controller) {\n    controller.enqueue(csv);\n    controller.close();\n  },\n});\n\nfor await (const record of parse(stream)) {\n  console.log(record);\n}\n// Prints:\n// { name: 'Alice', age: '42' }\n// { name: 'Bob', age: '69' }\n```\n\n### Parsing CSV files from `Response` objects\n\n```js\nimport { parse } from 'web-csv-toolbox';\n\nconst response = await fetch('https://example.com/data.csv');\n\nfor await (const record of parse(response)) {\n  console.log(record);\n}\n// Prints:\n// { name: 'Alice', age: '42' }\n// { name: 'Bob', age: '69' }\n```\n\n### Parsing CSV files from `Blob` or `File` objects\n\n```js\nimport { parse } from 'web-csv-toolbox';\n\n// From file input\nconst fileInput = document.querySelector('input[type=\"file\"]');\nfileInput.addEventListener('change', async (e) =\u003e {\n  const file = e.target.files[0];\n\n  for await (const record of parse(file)) {\n    console.log(record);\n  }\n  // Prints:\n  // { name: 'Alice', age: '42' }\n  // { name: 'Bob', age: '69' }\n});\n```\n\n### Parsing CSV files from `Request` objects (Server-side)\n\n```js\nimport { parse } from 'web-csv-toolbox';\n\n// Cloudflare Workers / Service Workers\nexport default {\n  async fetch(request) {\n    if (request.method === 'POST') {\n      for await (const record of parse(request)) {\n        console.log(record);\n      }\n      // Prints:\n      // { name: 'Alice', age: '42' }\n      // { name: 'Bob', age: '69' }\n\n      return new Response('OK', { status: 200 });\n    }\n  }\n};\n```\n\n### Parsing CSV files with different delimiters and quotation characters\n\n```js\nimport { parse } from 'web-csv-toolbox';\n\nconst csv = `name\\tage\nAlice\\t42\nBob\\t69`;\n\nfor await (const record of parse(csv, { delimiter: '\\t' })) {\n  console.log(record);\n}\n// Prints:\n// { name: 'Alice', age: '42' }\n// { name: 'Bob', age: '69' }\n```\n\n### Parsing CSV files with headers\n\n```js\nimport { parse } from 'web-csv-toolbox';\n\nconst csv = `Alice,42\nBob,69`;\n\nfor await (const record of parse(csv, { header: ['name', 'age'] })) {\n  console.log(record);\n}\n// Prints:\n// { name: 'Alice', age: '42' }\n// { name: 'Bob', age: '69' }\n```\n\n### Working with Headerless CSV Files\n\nSome CSV files don’t include a header row. You can provide custom headers manually:\n\n```typescript\nimport { parse } from 'web-csv-toolbox';\n\n// Example: Sensor data without headers\nconst sensorData = `25.5,60,1024\n26.1,58,1020\n24.8,62,1025`;\n\n// Provide headers explicitly\nfor await (const record of parse(sensorData, {\n  header: ['temperature', 'humidity', 'pressure']\n})) {\n  console.log(`Temp: ${record.temperature}°C, Humidity: ${record.humidity}%, Pressure: ${record.pressure} hPa`);\n}\n// Output:\n// Temp: 25.5°C, Humidity: 60%, Pressure: 1024 hPa\n// Temp: 26.1°C, Humidity: 58%, Pressure: 1020 hPa\n// Temp: 24.8°C, Humidity: 62%, Pressure: 1025 hPa\n```\n\n### `AbortSignal` / `AbortController` Support\n\nSupport for [`AbortSignal`](https://developer.mozilla.org/docs/Web/API/AbortSignal) / [`AbortController`](https://developer.mozilla.org/docs/Web/API/AbortController), enabling you to cancel ongoing asynchronous CSV processing tasks.\n\nThis feature is useful for scenarios where processing needs to be halted, such as when a user navigates away from the page or other conditions that require stopping the task early.\n\n#### Example Use Case: Abort with user action\n\n```js\nimport { parse } from 'web-csv-toolbox';\n\nconst controller = new AbortController();\nconst csv = \"name,age\\nAlice,30\\nBob,25\";\n\ntry {\n  // Parse the CSV data then pass the AbortSignal to the parse function\n  for await (const record of parse(csv, { signal: controller.signal })) {\n    console.log(record);\n  }\n} catch (error) {\n  if (error instanceof DOMException \u0026\u0026 error.name === 'AbortError') {\n     // The CSV processing was aborted by the user\n    console.log('CSV processing was aborted by the user.');\n  } else {\n    // An error occurred during CSV processing\n    console.error('An error occurred:', error);\n  }\n}\n\n// Some abort logic, like a cancel button\ndocument.getElementById('cancel-button')\n  .addEventListener('click', () =\u003e {\n    controller.abort();\n  });\n```\n\n#### Example Use Case: Abort with timeout\n\n```js\nimport { parse } from 'web-csv-toolbox';\n\n// Set up a timeout of 5 seconds (5000 milliseconds)\nconst signal = AbortSignal.timeout(5000);\n\nconst csv = \"name,age\\nAlice,30\\nBob,25\";\n\ntry {\n  // Pass the AbortSignal to the parse function\n  const result = await parse.toArray(csv, { signal });\n  console.log(result);\n} catch (error) {\n  if (error instanceof DOMException \u0026\u0026 error.name === 'TimeoutError') {\n    // Handle the case where the processing was aborted due to timeout\n    console.log('CSV processing was aborted due to timeout.');\n  } else {\n    // Handle other errors\n    console.error('An error occurred during CSV processing:', error);\n  }\n}\n```\n\n## Supported Runtimes 💻\n\n### Works on Node.js\n\n| Versions | Status |\n| -------- | ------ |\n| 20.x     | ✅     |\n| 22.x     | ✅     |\n| 24.x     | ✅     |\n\n\u003e Note: For Node environments, the WASM loader uses `import.meta.resolve`. Node.js 20.6+ is recommended. On older Node versions, pass an explicit URL/Buffer to `loadWASM()`.\n\n\n### Works on Browser\n\n| OS      | Chrome | Firefox | Default       |\n| ------- | ------ | ------- | ------------- |\n| Windows | ✅     | ✅      | ✅ (Edge)     |\n| macOS   | ✅     | ✅      | ⬜ (Safari *) |\n| Linux   | ✅     | ✅      | -             |\n\n\u003e **\\* Safari**: Basic functionality is expected to work, but it is not yet automatically tested in our CI environment.\n\n### Others\n\n- Verify that JavaScript is executable on the Deno. [![Deno CI](https://github.com/kamiazya/web-csv-toolbox/actions/workflows/deno.yaml/badge.svg)](https://github.com/kamiazya/web-csv-toolbox/actions/workflows/deno.yaml)\n\n### Platform-Specific Usage Guide 📚\n\nFor detailed examples and best practices for your specific runtime environment, see:\n\n**[Platform-Specific Usage Guide](./docs/how-to-guides/platform-usage/)**\n\nThis guide covers:\n- 🌐 **Browser**: File input, drag-and-drop, Clipboard API, FormData, Fetch API\n- 🟢 **Node.js**: Buffer, fs.ReadStream, HTTP requests, stdin/stdout\n- 🦕 **Deno**: Deno.readFile, Deno.open, fetch API\n- ⚡ **Edge**: Cloudflare Workers, Deno Deploy, Vercel Edge Functions\n- 🐰 **Bun**: File API, HTTP server\n\n## APIs 🧑‍💻\n\n### High-level APIs 🚀\n\nThese APIs are designed for **Simplicity and Ease of Use**,\nproviding an intuitive and straightforward experience for users.\n\n- **`function parse(input[, options]): AsyncIterableIterator\u003cCSVRecord\u003e`**: [📑](https://kamiazya.github.io/web-csv-toolbox/functions/parse-1.html)\n  - Parses various CSV input formats into an asynchronous iterable of records.\n- **`function parse.toArray(input[, options]): Promise\u003cCSVRecord[]\u003e`**: [📑](https://kamiazya.github.io/web-csv-toolbox/functions/parse.toArray.html)\n  - Parses CSV input into an array of records, ideal for smaller data sets.\n\nThe `input` paramater can be:\n- a `string`\n- a [ReadableStream](https://developer.mozilla.org/docs/Web/API/ReadableStream) of `string`s or [Uint8Array](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Uint8Array)s\n- a [BufferSource](https://webidl.spec.whatwg.org/#BufferSource) ([Uint8Array](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Uint8Array), [ArrayBuffer](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/ArrayBuffer), or other [TypedArray](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/TypedArray))\n- a [Response](https://developer.mozilla.org/docs/Web/API/Response) object\n- a [Blob](https://developer.mozilla.org/docs/Web/API/Blob) or [File](https://developer.mozilla.org/docs/Web/API/File) object\n- a [Request](https://developer.mozilla.org/docs/Web/API/Request) object (server-side)\n\n### Middle-level APIs 🧱\n\nThese APIs are optimized for **Enhanced Performance and Control**,\ncatering to users who need more detailed and fine-tuned functionality.\n\n- **`function parseString(string[, options])`**: [📑](https://kamiazya.github.io/web-csv-toolbox/functions/parseString-1.html)\n  - Efficient parsing of CSV strings.\n- **`function parseBinary(buffer[, options])`**: [📑](https://kamiazya.github.io/web-csv-toolbox/functions/parseBinary-1.html)\n  - Parse CSV binary data from BufferSource (Uint8Array, ArrayBuffer, or other TypedArray).\n- **`function parseResponse(response[, options])`**: [📑](https://kamiazya.github.io/web-csv-toolbox/functions/parseResponse-1.html)\n  - Customized parsing directly from `Response` objects.\n- **`function parseRequest(request[, options])`**: [📑](https://kamiazya.github.io/web-csv-toolbox/functions/parseRequest-1.html)\n  - Server-side parsing from `Request` objects (Cloudflare Workers, Service Workers, etc.).\n- **`function parseBlob(blob[, options])`**: [📑](https://kamiazya.github.io/web-csv-toolbox/functions/parseBlob-1.html)\n  - Parse CSV data from `Blob` or `File` objects.\n- **`function parseFile(file[, options])`**: [📑](https://kamiazya.github.io/web-csv-toolbox/functions/parseFile-1.html)\n  - Parse `File` objects with automatic filename tracking in error messages.\n- **`function parseStream(stream[, options])`**: [📑](https://kamiazya.github.io/web-csv-toolbox/functions/parseStream-1.html)\n  - Stream-based parsing for larger or continuous data.\n- **`function parseStringStream(stream[, options])`**: [📑](https://kamiazya.github.io/web-csv-toolbox/functions/parseStringStream-1.html)\n  - Combines string-based parsing with stream processing.\n- **`function parseBinaryStream(stream[, options])`**: [📑](https://kamiazya.github.io/web-csv-toolbox/functions/parseBinaryStream-1.html)\n  - Parses binary streams with precise control over data types.\n\n### Low-level APIs ⚙️\n\nThese APIs are built for **Advanced Customization and Pipeline Design**,\nideal for developers looking for in-depth control and flexibility.\n\nThe low-level APIs follow a 3-tier architecture:\n\n#### Parser Models (Tier 1: Simplified Composition)\n\nCombines Lexer and Assembler for streamlined usage without sacrificing flexibility.\n\n- **`function createStringCSVParser(options?)`**\n  - Factory function for creating format-specific CSV parsers.\n  - Returns `FlexibleStringObjectCSVParser` (default) or `FlexibleStringArrayCSVParser` based on `outputFormat` option.\n  - Parses CSV strings by composing `FlexibleStringCSVLexer` and CSV Record Assembler.\n  - Stateful parser maintains internal lexer and assembler instances for streaming.\n  - Use with `StringCSVParserStream` for streaming workflows.\n  - **Low-level API**: Accepts `CSVProcessingOptions` only (no `engine` option).\n  - **Streaming mode**: When using `parse(chunk, { stream: true })`, you must call `parse()` without arguments at the end to flush any remaining data.\n\n  ```typescript\n  // Object format (default)\n  const objectParser = createStringCSVParser({\n    header: ['name', 'age']\n  });\n\n  // Array format\n  const arrayParser = createStringCSVParser({\n    header: ['name', 'age'],\n    outputFormat: 'array'\n  });\n\n  // Process chunks\n  const records1 = objectParser.parse('Alice,30\\nBob,', { stream: true });\n  const records2 = objectParser.parse('25\\nCharlie,', { stream: true });\n\n  // Flush remaining data (required!)\n  const records3 = objectParser.parse();\n  ```\n\n  - **Direct class usage**:\n    - `FlexibleStringObjectCSVParser` - Always outputs object records\n    - `FlexibleStringArrayCSVParser` - Always outputs array records\n\n- **`function createBinaryCSVParser(options?)`**\n  - Factory function for creating format-specific binary CSV parsers.\n  - Returns `FlexibleBinaryObjectCSVParser` (default) or `FlexibleBinaryArrayCSVParser` based on `outputFormat` option.\n  - Parses binary CSV data (BufferSource: Uint8Array, ArrayBuffer, or other TypedArray) by composing `TextDecoder` with string CSV parser.\n  - Uses `TextDecoder` with `stream: true` option for proper multi-byte character handling across chunk boundaries.\n  - Supports various character encodings (utf-8, shift_jis, etc.) via `charset` option.\n  - BOM handling via `ignoreBOM` option, fatal error mode via `fatal` option.\n  - Use with `BinaryCSVParserStream` for streaming workflows.\n  - **Low-level API**: Accepts `BinaryCSVProcessingOptions` only (no `engine` option).\n  - **Streaming mode**: When using `parse(chunk, { stream: true })`, you must call `parse()` without arguments at the end to flush TextDecoder and parser buffers.\n\n  ```typescript\n  // Object format (default)\n  const objectParser = createBinaryCSVParser({\n    header: ['name', 'age'],\n    charset: 'utf-8'\n  });\n\n  // Array format\n  const arrayParser = createBinaryCSVParser({\n    header: ['name', 'age'],\n    outputFormat: 'array',\n    charset: 'utf-8'\n  });\n\n  const encoder = new TextEncoder();\n\n  // Process chunks\n  const records1 = objectParser.parse(encoder.encode('Alice,30\\nBob,'), { stream: true });\n  const records2 = objectParser.parse(encoder.encode('25\\n'), { stream: true });\n\n  // Flush remaining data (required!)\n  const records3 = objectParser.parse();\n  ```\n\n  - **Direct class usage**:\n    - `FlexibleBinaryObjectCSVParser` - Always outputs object records\n    - `FlexibleBinaryArrayCSVParser` - Always outputs array records\n\n#### Lexer (Tier 2: Stage 1 - Tokenization)\n\nLow-level tokenization with full control over CSV syntax.\n\n- **`function createStringCSVLexer(options?)` / `class FlexibleStringCSVLexer`**\n  - Factory helper plus underlying class for the standalone lexer used across the toolkit.\n  - Configure delimiters, quotation, buffer limits, and cancellation per stream.\n  - Returns tokens (field values, row delimiters, etc.) for manual processing.\n\n#### Assembler (Tier 2: Stage 2 - Record Assembly)\n\nConverts tokens into structured records with flexible formatting.\n\n- **`function createCSVRecordAssembler(options)`**\n  - Factory that returns either an object- or array-format assembler based on `outputFormat`.\n  - Applies new options like `includeHeader` and `columnCountStrategy` consistently across environments.\n- **`class FlexibleCSVObjectRecordAssembler` / `class FlexibleCSVArrayRecordAssembler`**\n  - Specialized assemblers when you need full control over object vs tuple output or want to extend behavior.\n  - `FlexibleCSVRecordAssembler` remains for backward compatibility but now delegates to these focused implementations.\n\n#### Streaming Transformers (Tier 3: TransformStream Integration)\n\nWeb Streams API integration for all processing tiers.\n\n- **`class StringCSVParserStream`**\n  - `TransformStream\u003cstring, CSVRecord\u003e` for streaming string parsing.\n  - Wraps Parser instances (accepts parser in constructor, doesn't construct internally).\n  - Configurable backpressure handling via `backpressureCheckInterval` option.\n  - Custom queuing strategies support for fine-tuned performance.\n- **`class BinaryCSVParserStream`**\n  - `TransformStream\u003cBufferSource, CSVRecord\u003e` for streaming binary parsing.\n  - Handles UTF-8 multi-byte characters across chunk boundaries.\n  - Integration-ready for fetch API and file streaming.\n  - Backpressure management with configurable check intervals.\n- **`createStringCSVLexerTransformer()`**: [📑](https://kamiazya.github.io/web-csv-toolbox/functions/createStringCSVLexerTransformer.html)\n  - Factory function to create a StringCSVLexerTransformer with customizable queuing strategies.\n- **`createCSVRecordAssemblerTransformer()`**: [📑](https://kamiazya.github.io/web-csv-toolbox/functions/createCSVRecordAssemblerTransformer.html)\n  - Factory function to create a CSVRecordAssemblerTransformer with cooperative backpressure support.\n\nThese factory functions are the recommended way to create transformer instances. They encapsulate internal lexer/assembler initialization and provide sensible defaults, insulating your code from internal implementation changes. Direct class instantiation (`new StringCSVLexerTransformer(customLexer)`) is only needed when injecting a custom lexer implementation—see [Custom Lexer/Assembler](./docs/how-to-guides/custom-csv-parser.md#low-level-custom-lexerassembler) for advanced use cases.\n\n#### Customizing Queuing Strategies\n\nBoth `createStringCSVLexerTransformer()` and `createCSVRecordAssemblerTransformer()` support custom queuing strategies following the Web Streams API pattern. Strategies are passed as function arguments with **data-type-aware size counting** and **configurable backpressure handling**.\n\n**Function signature:**\n```typescript\ncreateStringCSVLexerTransformer(options?, streamOptions?, writableStrategy?, readableStrategy?)\ncreateCSVRecordAssemblerTransformer(options?, streamOptions?, writableStrategy?, readableStrategy?)\n```\n\n**Default queuing strategies (starting points, not benchmarked):**\n```typescript\n// StringCSVLexerTransformer defaults\ncreateStringCSVLexerTransformer(\n  { delimiter: ',' },                  // CSV options\n  { backpressureCheckInterval: 100 },  // Check every 100 tokens\n  {\n    highWaterMark: 65536,              // 64KB of characters\n    size: (chunk) =\u003e chunk.length,     // Count by string length\n  },\n  new CountQueuingStrategy({ highWaterMark: 1024 })  // 1024 tokens\n)\n\n// CSVRecordAssemblerTransformer defaults\ncreateCSVRecordAssemblerTransformer(\n  { header: ['name', 'age'] },         // Assembler options\n  { backpressureCheckInterval: 10 },   // Check every 10 records\n  new CountQueuingStrategy({ highWaterMark: 1024 }),  // 1024 tokens\n  new CountQueuingStrategy({ highWaterMark: 256 })    // 256 records\n)\n```\n\n**Key Features:**\n\n🎯 **Smart Size Counting:**\n- Character-based counting for string inputs (accurate memory tracking)\n- Token-based counting between transformers (smooth pipeline flow)\n- Record-based counting for output (intuitive and predictable)\n\n⚡ **Cooperative Backpressure:**\n- Monitors `controller.desiredSize` during processing\n- Yields to event loop when backpressure detected\n- Prevents blocking the main thread\n- Critical for browser UI responsiveness\n\n🔧 **Tunable Backpressure Check Interval:**\n- `backpressureCheckInterval` (in options): How often to check for backpressure (count-based)\n- Lower values (5-25): More responsive, slight overhead\n- Higher values (100-500): Less overhead, slower response\n- Customize based on downstream consumer speed\n\n\u003e ⚠️ **Important**: These defaults are theoretical starting points based on data flow characteristics, **not empirical benchmarks**. Optimal values vary by runtime (browser/Node.js/Deno), file size, memory constraints, and CPU performance. **Profile your specific use case** to find the best values.\n\n**When to customize:**\n- 🚀 **High-throughput servers**: Higher `highWaterMark` (128KB+, 2048+ tokens), higher `backpressureCheckInterval` (200-500)\n- 📱 **Memory-constrained environments**: Lower `highWaterMark` (16KB, 256 tokens), lower `backpressureCheckInterval` (10-25)\n- 🐌 **Slow consumers** (DB writes, API calls): Lower `highWaterMark`, lower `backpressureCheckInterval` for responsive backpressure\n- 🏃 **Fast processing**: Higher values to reduce overhead\n\n**Example - High-throughput server:**\n```typescript\nimport {\n  createStringCSVLexerTransformer,\n  createCSVRecordAssemblerTransformer\n} from 'web-csv-toolbox';\n\nconst response = await fetch('large-dataset.csv');\nawait response.body\n  .pipeThrough(new TextDecoderStream())\n  .pipeThrough(createStringCSVLexerTransformer(\n    { delimiter: ',' },\n    { backpressureCheckInterval: 200 },  // Less frequent checks\n    {\n      highWaterMark: 131072,             // 128KB\n      size: (chunk) =\u003e chunk.length,\n    },\n    new CountQueuingStrategy({ highWaterMark: 2048 })  // 2048 tokens\n  ))\n  .pipeThrough(createCSVRecordAssemblerTransformer(\n    {},                                  // Use default assembler options\n    { backpressureCheckInterval: 20 },   // Less frequent checks\n    new CountQueuingStrategy({ highWaterMark: 2048 }),  // 2048 tokens\n    new CountQueuingStrategy({ highWaterMark: 512 })    // 512 records\n  ))\n  .pipeTo(yourRecordProcessor);\n```\n\n**Example - Slow consumer (API writes):**\n```typescript\nimport {\n  createStringCSVLexerTransformer,\n  createCSVRecordAssemblerTransformer\n} from 'web-csv-toolbox';\n\nawait csvStream\n  .pipeThrough(createStringCSVLexerTransformer())  // Use defaults\n  .pipeThrough(createCSVRecordAssemblerTransformer(\n    {},                                  // Use default assembler options\n    { backpressureCheckInterval: 2 },    // Very responsive\n    new CountQueuingStrategy({ highWaterMark: 512 }),\n    new CountQueuingStrategy({ highWaterMark: 64 })\n  ))\n  .pipeTo(new WritableStream({\n    async write(record) {\n      await fetch('/api/save', { method: 'POST', body: JSON.stringify(record) });\n    }\n  }));\n```\n\n**Benchmarking:**\nUse the provided benchmark tool to find optimal values for your use case:\n```bash\npnpm --filter web-csv-toolbox-benchmark queuing-strategy\n```\n\nSee `benchmark/queuing-strategy.bench.ts` for implementation details.\n\n### Experimental APIs 🧪\n\nThese APIs are experimental and may change in the future.\n\n#### Parsing using WebAssembly for high performance.\n\nYou can use WebAssembly to parse CSV data for high performance.\n\n⚠️ **Experimental Notice**:\n- WASM automatic initialization is experimental and may change in future versions\n- Currently embeds WASM as base64 in the main bundle\n- Future versions may change the loading strategy for better bundle size optimization\n\n**WASM Limitations:**\n- Parsing with WebAssembly is faster than parsing with JavaScript,\nbut it takes time to load the WebAssembly module.\n- Supports only UTF-8 encoding csv data.\n- Quotation characters are only `\"`. (Double quotation mark)\n  - If you pass a different character, it will throw an error.\n- Record output is always object-shaped; `outputFormat: 'array'` requires the JavaScript engine (`engine: { wasm: false }`).\n\n```ts\nimport { loadWASM, parseStringToArraySyncWASM } from \"web-csv-toolbox\";\n\n// load WebAssembly module\nawait loadWASM();\n\nconst csv = \"a,b,c\\n1,2,3\";\n\n// parse CSV string\nconst result = parseStringToArraySyncWASM(csv);\nconsole.log(result);\n// Prints:\n// [{ a: \"1\", b: \"2\", c: \"3\" }]\n```\n\n- **`function loadWASM(): Promise\u003cvoid\u003e`**: [📑](https://kamiazya.github.io/web-csv-toolbox/functions/loadWASM.html)\n  - Loads the WebAssembly module.\n- **`function parseStringToArraySyncWASM(string[, options]): CSVRecord[]`**: [📑](https://kamiazya.github.io/web-csv-toolbox/functions/parseStringToArraySyncWASM.html)\n  - Parses CSV strings into an array of records.\n\n## Options Configuration 🛠️\n\n### Common Options ⚙️\n\n| Option           | Description                           | Default      | Notes                                                                              |\n| ---------------- | ------------------------------------- | ------------ | ---------------------------------------------------------------------------------- |\n| `delimiter`      | Character to separate fields          | `,`          |                                                                                    |\n| `quotation`      | Character used for quoting fields     | `\"`          |                                                                                    |\n| `maxBufferSize`  | Maximum internal buffer size (characters)  | `10 * 1024 * 1024`   | Set to `Number.POSITIVE_INFINITY` to disable (not recommended for untrusted input). Measured in UTF-16 code units. |\n| `maxFieldCount`  | Maximum fields allowed per record     | `100000`     | Set to `Number.POSITIVE_INFINITY` to disable (not recommended for untrusted input) |\n| `header`         | Custom headers for the parsed records | First row    | If not provided, the first row is used as headers                                  |\n| `outputFormat`   | Record shape (`'object'` or `'array'`) | `'object'`   | `'array'` returns type-safe tuples; not available when running through WASM today |\n| `includeHeader`  | Emit header row when using array output | `false` | Only valid with `outputFormat: 'array'` — the header becomes the first emitted record |\n| `columnCountStrategy` | Handle column-count mismatches when a header is provided | `'keep'` for array format / `'pad'` for object format | Choose between `keep`, `pad`, `strict`, or `truncate` to control how rows align with the header |\n| `signal`         | AbortSignal to cancel processing      | `undefined`  | Allows aborting of long-running operations                                         |\n\n#### Record Output Formats\n\nHigh-level and mid-level parsers now let you choose whether records come back as objects (default) or as tuple-like arrays:\n\n```ts\nconst header = [\"name\", \"age\"];\n\n// Object output (default)\nfor await (const record of parse(csv, { header })) {\n  record.name; // string\n}\n\n// Array output with named tuples\nconst rows = await parse.toArray(csv, {\n  header,\n  outputFormat: \"array\",\n  includeHeader: true,\n  columnCountStrategy: \"pad\",\n  engine: { wasm: false }, // Array output currently runs on the JS engine only\n});\n// rows[0] === ['name', 'age'] (header row)\n// rows[1] has type readonly [name: string, age: string]\n```\n\n- `outputFormat: 'object'` (default) returns familiar `{ column: value }` objects.\n- `outputFormat: 'array'` returns readonly tuples whose indices inherit names from the header for stronger TypeScript inference.\n- `includeHeader: true` prepends the header row when you also set `outputFormat: 'array'`.\n- `columnCountStrategy` controls how rows with too many or too few columns are treated when a header is present:\n  - `keep`: emit rows exactly as they appear (default for array output with inferred headers)\n  - `pad`: fill short rows with `undefined` and truncate long rows (default for object output)\n  - `strict`: throw if the row length differs from the header\n  - `truncate`: discard columns beyond the header length without padding short rows\n\n\u003e ⚠️ Array output is not yet available inside the WebAssembly execution path. If you request `outputFormat: 'array'`, force the JavaScript engine with `engine: { wasm: false }` (or run in an environment where WASM is disabled).\n\n### Advanced Options (Binary-Specific) 🧬\n\n| Option                            | Description                                       | Default | Notes                                                                                                                                                     |\n| --------------------------------- | ------------------------------------------------- | ------- | --------------------------------------------------------------------------------------------------------------------------------------------------------- |\n| `charset`                         | Character encoding for binary CSV inputs          | `utf-8` | See [Encoding API Compatibility](https://developer.mozilla.org/en-US/docs/Web/API/Encoding_API/Encodings) for the encoding formats that can be specified. |\n| `maxBinarySize`                   | Maximum binary size for BufferSource inputs (bytes) | `100 * 1024 * 1024` (100MB) | Set to `Number.POSITIVE_INFINITY` to disable (not recommended for untrusted input) |\n| `decompression`                   | Decompression algorithm for compressed CSV inputs |         | See [DecompressionStream Compatibility](https://developer.mozilla.org/en-US/docs/Web/API/DecompressionStream#browser_compatibility). Default support: gzip, deflate. deflate-raw is runtime-dependent and experimental (requires `allowExperimentalCompressions: true` for Response/Request inputs). |\n| `ignoreBOM`                       | Whether to ignore Byte Order Mark (BOM)           | `false` | See [TextDecoderOptions.ignoreBOM](https://developer.mozilla.org/en-US/docs/Web/API/TextDecoderStream/ignoreBOM) for more information about the BOM.      |\n| `fatal`                           | Throw an error on invalid characters              | `false` | See [TextDecoderOptions.fatal](https://developer.mozilla.org/en-US/docs/Web/API/TextDecoderStream/fatal) for more information.                            |\n| `allowExperimentalCompressions`   | Allow experimental/future compression formats     | `false` | When enabled, passes unknown compression formats to runtime. Use cautiously. See example below.                                                           |\n\n## Performance \u0026 Best Practices ⚡\n\n### Memory Characteristics\n\nweb-csv-toolbox uses different memory patterns depending on the API you choose:\n\n#### 🌊 Streaming APIs (Memory Efficient)\n\n##### Recommended for large files (\u003e 10MB)\n\n```js\nimport { parse } from 'web-csv-toolbox';\n\n// ✅ Memory efficient: processes one record at a time\nconst response = await fetch('https://example.com/large-data.csv');\nfor await (const record of parse(response)) {\n  console.log(record);\n  // Memory footprint: ~few KB per iteration\n}\n```\n\n- **Memory usage**: O(1) - constant per record\n- **Suitable for**: Files of any size, browser environments\n- **Max file size**: Limited only by available storage/network\n\n#### 📦 Array-Based APIs (Memory Intensive)\n\n##### Recommended for small files (\u003c 1MB)\n\n```js\nimport { parse } from 'web-csv-toolbox';\n\n// ⚠️ Loads entire result into memory\nconst csv = await fetch('data.csv').then(r =\u003e r.text());\nconst records = await parse.toArray(csv);\n// Memory footprint: entire file + parsed array\n```\n\n- **Memory usage**: O(n) - proportional to file size\n- **Suitable for**: Small datasets, quick prototyping\n- **Recommended max**: ~10MB (browser), ~100MB (Node.js)\n\n### Platform-Specific Considerations\n\n| Platform | Streaming | Array-Based | Notes |\n|----------|-----------|-------------|-------|\n| **Browser** | Any size | \u003c 10MB | Browser heap limits apply (~100MB-4GB depending on browser) |\n| **Node.js** | Any size | \u003c 100MB | Use `--max-old-space-size` flag for larger heaps |\n| **Deno** | Any size | \u003c 100MB | Similar to Node.js |\n\n### Performance Tips\n\n#### 1. Use streaming for large files\n\n```js\nimport { parse } from 'web-csv-toolbox';\n\nconst response = await fetch('https://example.com/large-data.csv');\n\n// ✅ Good: Streaming approach (constant memory usage)\nfor await (const record of parse(response)) {\n  // Process each record immediately\n  console.log(record);\n  // Memory footprint: O(1) - only one record in memory at a time\n}\n\n// ❌ Avoid: Loading entire file into memory first\nconst response2 = await fetch('https://example.com/large-data.csv');\nconst text = await response2.text(); // Loads entire file into memory\nconst records = await parse.toArray(text); // Loads all records into memory\nfor (const record of records) {\n  console.log(record);\n  // Memory footprint: O(n) - entire file + all records in memory\n}\n```\n\n#### 2. Enable AbortSignal for timeout protection\n\n```js\nimport { parse } from 'web-csv-toolbox';\n\n// Set up a timeout of 30 seconds (30000 milliseconds)\nconst signal = AbortSignal.timeout(30000);\n\nconst response = await fetch('https://example.com/large-data.csv');\n\ntry {\n  for await (const record of parse(response, { signal })) {\n    // Process each record\n    console.log(record);\n  }\n} catch (error) {\n  if (error instanceof DOMException \u0026\u0026 error.name === 'TimeoutError') {\n    // Handle timeout\n    console.log('CSV processing was aborted due to timeout.');\n  } else {\n    // Handle other errors\n    console.error('An error occurred during CSV processing:', error);\n  }\n}\n```\n\n#### 3. Use WebAssembly parser for CPU-intensive workloads (Experimental)\n\n```js\nimport { parseStringToArraySyncWASM } from 'web-csv-toolbox';\n\n// Compiled WASM code for improved performance (UTF-8 only)\n// See CodSpeed benchmarks for actual performance metrics\nconst records = parseStringToArraySyncWASM(csvString);\n```\n\n### Known Limitations\n\n- **Delimiter/Quotation**: Must be a single character (multi-character delimiters not supported)\n- **WASM Parser**: UTF-8 encoding only, double-quote (`\"`) only\n- **Streaming**: Best performance with chunk sizes \u003e 1KB\n\n### Security Considerations\n\nFor production use with untrusted input, consider:\n- Setting timeouts using `AbortSignal.timeout()` to prevent resource exhaustion\n- Using `maxBinarySize` option to limit BufferSource inputs (default: 100MB bytes)\n- Using `maxBufferSize` option to limit internal buffer size (default: 10M characters)\n- Using `maxFieldCount` option to limit fields per record (default: 100,000)\n- Implementing additional file size limits at the application level\n- Validating parsed data before use\n\n#### Implementing Size Limits for Untrusted Sources\n\nWhen processing CSV files from untrusted sources (especially compressed files), you can implement size limits using a custom TransformStream:\n\n```js\nimport { parse } from 'web-csv-toolbox';\n\n// Create a size-limiting TransformStream\nclass SizeLimitStream extends TransformStream {\n  constructor(maxBytes) {\n    let bytesRead = 0;\n    super({\n      transform(chunk, controller) {\n        bytesRead += chunk.length;\n        if (bytesRead \u003e maxBytes) {\n          controller.error(new Error(`Size limit exceeded: ${maxBytes} bytes`));\n        } else {\n          controller.enqueue(chunk);\n        }\n      }\n    });\n  }\n}\n\n// Example: Limit decompressed data to 10MB\nconst response = await fetch('https://untrusted-source.com/data.csv.gz');\nconst limitedStream = response.body\n  .pipeThrough(new DecompressionStream('gzip'))\n  .pipeThrough(new SizeLimitStream(10 * 1024 * 1024)); // 10MB limit\n\ntry {\n  for await (const record of parse(limitedStream)) {\n    console.log(record);\n  }\n} catch (error) {\n  if (error.message.includes('Size limit exceeded')) {\n    console.error('File too large - possible compression bomb attack');\n  }\n}\n```\n\n**Note**: The library automatically validates Content-Encoding headers when parsing Response objects, rejecting unsupported compression formats.\n\n#### Using Experimental Compression Formats\n\nBy default, the library only supports well-tested compression formats: `gzip` and `deflate`. Some runtimes may support additional formats like `deflate-raw` or Brotli, but these are runtime-dependent and not guaranteed. If you need to use these formats, you can enable experimental mode:\n\n```js\nimport { parse } from 'web-csv-toolbox';\n\n// ✅ Default behavior: Only known formats\nconst response = await fetch('data.csv.gz');\nawait parse(response); // Works\n\n// ⚠️ Experimental: Allow future formats\nconst response2 = await fetch('data.csv.br'); // Brotli compression\ntry {\n  await parse(response2, { allowExperimentalCompressions: true });\n  // Works if runtime supports Brotli\n} catch (error) {\n  // Runtime will throw if format is unsupported\n  console.error('Runtime does not support this compression format');\n}\n```\n\n**When to use this:**\n- Your runtime supports a newer compression format (e.g., Brotli in modern browsers)\n- You want to use the format before this library explicitly supports it\n- You trust the compression format source\n\n**Cautions:**\n- Error messages will come from the runtime, not this library\n- No library-level validation for unknown formats\n- You must verify your runtime supports the format\n\n## How to Contribute 💪\n\n## Star ⭐\n\nThe easiest way to contribute is to use the library and star the [repository](https://github.com/kamiazya/web-csv-toolbox/).\n\n### Questions 💭\n\nFeel free to ask questions on [GitHub Discussions](https://github.com/kamiazya/web-csv-toolbox/discussions).\n\n### Report bugs / request additional features 💡\n\nPlease create an issue at [GitHub Issues](https://github.com/kamiazya/web-csv-toolbox/issues/new/choose).\n\n### Financial Support 💸\n\nPlease support [kamiazya](https://github.com/sponsors/kamiazya).\n\n\u003e Even just a dollar is enough motivation to develop 😊\n\n## License ⚖️\n\nThis software is released under the MIT License, see [LICENSE](https://github.com/kamiazya/web-csv-toolbox/blob/main/LICENSE).\n\n\n[![FOSSA Status](https://app.fossa.com/api/projects/git%2Bgithub.com%2Fkamiazya%2Fweb-csv-toolbox.svg?type=large)](https://app.fossa.com/projects/git%2Bgithub.com%2Fkamiazya%2Fweb-csv-toolbox?ref=badge_large)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fkamiazya%2Fweb-csv-toolbox","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fkamiazya%2Fweb-csv-toolbox","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fkamiazya%2Fweb-csv-toolbox/lists"}