{"id":13564706,"url":"https://github.com/arcjet/arcjet-js","last_synced_at":"2025-10-19T08:19:47.337Z","repository":{"id":221754917,"uuid":"725458907","full_name":"arcjet/arcjet-js","owner":"arcjet","description":"Arcjet JS SDKs. Bot detection, rate limiting, email validation, attack protection, data redaction for Node.js, Next.js, Deno, Bun, Remix, SvelteKit, NestJS.","archived":false,"fork":false,"pushed_at":"2025-05-07T16:19:43.000Z","size":36993,"stargazers_count":425,"open_issues_count":77,"forks_count":14,"subscribers_count":5,"default_branch":"main","last_synced_at":"2025-05-08T02:18:46.567Z","etag":null,"topics":["bun","developer-tools","javascript","javascript-library","nextjs","nodejs","rate-limiting","remix","security","security-tools","serverless","sveltekit","typescript","typescript-library","webassembly"],"latest_commit_sha":null,"homepage":"https://arcjet.com","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/arcjet.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":".github/CODEOWNERS","security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null}},"created_at":"2023-11-30T07:25:40.000Z","updated_at":"2025-05-07T16:19:00.000Z","dependencies_parsed_at":"2024-06-10T08:14:27.008Z","dependency_job_id":"003ba604-015f-45bc-a8c8-0732ea069281","html_url":"https://github.com/arcjet/arcjet-js","commit_stats":{"total_commits":1304,"total_committers":8,"mean_commits":163.0,"dds":"0.22162576687116564","last_synced_commit":"7d9ac4f6401c2e47632c8dc97845f6cd3abf92f9"},"previous_names":["arcjet/arcjet-js"],"tags_count":40,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/arcjet%2Farcjet-js","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/arcjet%2Farcjet-js/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/arcjet%2Farcjet-js/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/arcjet%2Farcjet-js/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/arcjet","download_url":"https://codeload.github.com/arcjet/arcjet-js/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":254168805,"owners_count":22026206,"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","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":["bun","developer-tools","javascript","javascript-library","nextjs","nodejs","rate-limiting","remix","security","security-tools","serverless","sveltekit","typescript","typescript-library","webassembly"],"created_at":"2024-08-01T13:01:34.715Z","updated_at":"2025-10-19T08:19:47.315Z","avatar_url":"https://github.com/arcjet.png","language":"TypeScript","readme":"\u003ca href=\"https://arcjet.com\" target=\"_arcjet-home\"\u003e\n  \u003cpicture\u003e\n    \u003csource media=\"(prefers-color-scheme: dark)\" srcset=\"https://arcjet.com/logo/arcjet-dark-lockup-voyage-horizontal.svg\"\u003e\n    \u003cimg src=\"https://arcjet.com/logo/arcjet-light-lockup-voyage-horizontal.svg\" alt=\"Arcjet Logo\" height=\"128\" width=\"auto\"\u003e\n  \u003c/picture\u003e\n\u003c/a\u003e\n\n# Arcjet - JS SDK\n\n\u003cp\u003e\n  \u003cpicture\u003e\n    \u003csource media=\"(prefers-color-scheme: dark)\" srcset=\"https://img.shields.io/npm/v/arcjet?style=flat-square\u0026label=%E2%9C%A6Aj\u0026labelColor=000000\u0026color=5C5866\"\u003e\n    \u003cimg alt=\"npm badge\" src=\"https://img.shields.io/npm/v/arcjet?style=flat-square\u0026label=%E2%9C%A6Aj\u0026labelColor=ECE6F0\u0026color=ECE6F0\"\u003e\n  \u003c/picture\u003e\n\u003c/p\u003e\n\n[Arcjet][arcjet] helps developers protect their apps in just a few lines of\ncode. Bot detection. Rate limiting. Email validation. Attack protection. Data\nredaction. A developer-first approach to security.\n\nThis is the monorepo containing various [Arcjet][arcjet] open source packages\nfor JS.\n\n## Features\n\nArcjet security features for protecting JS apps:\n\n- 🤖 [Bot protection][bot-protection-quick-start] - manage traffic by automated\n  clients and bots.\n- 🛑 [Rate limiting][rate-limiting-quick-start] - limit the number of requests a\n  client can make.\n- 🛡️ [Shield WAF][shield-quick-start] - protect your application against common\n  attacks.\n- 📧 [Email validation][email-validation-quick-start] - prevent users from\n  signing up with fake email addresses.\n- 📝 [Signup form protection][signup-protection-quick-start] - combines rate\n  limiting, bot protection, and email validation to protect your signup forms.\n- 🕵️‍♂️ [Sensitive information detection][sensitive-info-quick-start] - block\n  personally identifiable information (PII).\n- 🚅 [Nosecone][nosecone-quick-start] - set security headers such as\n  `Content-Security-Policy` (CSP).\n\n## Quick start\n\n- [Astro][quick-start-astro]\n- [Bun + Hono][quick-start-bun-hono]\n- [Bun][quick-start-bun]\n- [Deno][quick-start-deno]\n- [Fastify][quick-start-fastify]\n- [NestJS][quick-start-nest-js]\n- [Next.js][quick-start-next-js]\n- [Node.js + Express][quick-start-node-js-express]\n- [Node.js + Hono][quick-start-node-js-hono]\n- [Node.js][quick-start-node-js]\n- [Remix][quick-start-remix]\n- [SvelteKit][quick-start-sveltekit]\n\n\u003c!--\nTODO: list `react-router` when done.\n--\u003e\n\n### Get help\n\n[Join our Discord server][discord-invite] or [reach out for support][support].\n\n## Example apps\n\n- [Astro][github-arcjet-example-astro]\n- [Express][github-arcjet-example-express]\n- [Fastify][github-arcjet-example-fastify]\n- [NestJS][github-arcjet-example-nestjs]\n- [Next.js: Bot protection][github-arcjet-example-nextjs-bot-protection]\n- [Next.js: Server action][github-arcjet-example-nextjs-server-action]\n- [Next.js: Form][github-arcjet-example-nextjs-form]\n- [Next.js][github-arcjet-example-nextjs] ([try live][arcjet-example])\n- [Remix][github-arcjet-example-remix]\n- [Tanstack Start][github-arcjet-example-tanstack-start]\n- …see also [many more examples here in `examples/`][file-examples]\n\n\u003c!--\nTODO: list `react-router` when done.\n--\u003e\n\n## Blueprints\n\n- [AI quota control][blueprint-ai-quota-control]\n- [IP geolocation][blueprint-ip-geolocation]\n- [Cookie banner][blueprint-cookie-banner]\n- [Payment form protection][blueprint-payment-form-protection]\n- [VPN \u0026 proxy detection][blueprint-vpn-proxy-detection]\n\n## Usage\n\nRead the docs at [docs.arcjet.com][arcjet-docs].\n\n### Next.js bot detection\n\nThis example will enable [Arcjet bot protection][bot-protection-concepts-docs]\nacross your entire Next.js application. Next.js middleware runs before every\nrequest, allowing Arcjet to protect your entire application before your code\nruns.\n\nIt will return a 403 Forbidden response for all requests from bots not in the\nallow list.\n\n```ts\n// middleware.ts\nimport arcjet, { ArcjetRuleResult, detectBot } from \"@arcjet/next\";\nimport { isSpoofedBot } from \"@arcjet/inspect\";\nimport { NextRequest, NextResponse } from \"next/server\";\n\nexport const config = {\n  // matcher tells Next.js which routes to run the middleware on.\n  // This runs the middleware on all routes except for static assets.\n  matcher: [\"/((?!_next/static|_next/image|favicon.ico).*)\"],\n};\nconst aj = arcjet({\n  key: process.env.ARCJET_KEY!, // Get your site key from https://app.arcjet.com\n  rules: [\n    detectBot({\n      mode: \"LIVE\", // will block requests. Use \"DRY_RUN\" to log only\n      // Block all bots except the following\n      allow: [\n        \"CATEGORY:SEARCH_ENGINE\", // Google, Bing, etc\n        // Uncomment to allow these other common bot categories\n        // See the full list at https://arcjet.com/bot-list\n        //\"CATEGORY:MONITOR\", // Uptime monitoring services\n        //\"CATEGORY:PREVIEW\", // Link previews e.g. Slack, Discord\n      ],\n    }),\n  ],\n});\n\nexport default async function middleware(request: NextRequest) {\n  const decision = await aj.protect(request);\n\n  // Bots not in the allow list will be blocked\n  if (decision.isDenied()) {\n    return NextResponse.json({ error: \"Forbidden\" }, { status: 403 });\n  }\n\n  // Arcjet Pro plan verifies the authenticity of common bots using IP data.\n  // Verification isn't always possible, so we recommend checking the results\n  // separately.\n  // https://docs.arcjet.com/bot-protection/reference#bot-verification\n  if (decision.results.some(isSpoofedBot)) {\n    return NextResponse.json({ error: \"Forbidden\" }, { status: 403 });\n  }\n\n  return NextResponse.next();\n}\n```\n\n### Node.js bot protection example\n\nThis simple Node.js server is protected with [Arcjet bot\nprotection][bot-protection-concepts-docs]. It will return a 403 Forbidden\nresponse for all requests from bots not in the allow list.\n\n```ts\n// server.ts\nimport arcjet, { detectBot } from \"@arcjet/node\";\nimport http from \"node:http\";\n\nconst aj = arcjet({\n  key: process.env.ARCJET_KEY!, // Get your site key from https://app.arcjet.com\n  rules: [\n    detectBot({\n      mode: \"LIVE\", // will block requests. Use \"DRY_RUN\" to log only\n      // configured with a list of bots to allow from\n      // https://arcjet.com/bot-list\n      // Block all bots except the following\n      allow: [\n        \"CATEGORY:SEARCH_ENGINE\", // Google, Bing, etc\n        // Uncomment to allow these other common bot categories\n        // See the full list at https://arcjet.com/bot-list\n        //\"CATEGORY:MONITOR\", // Uptime monitoring services\n        //\"CATEGORY:PREVIEW\", // Link previews e.g. Slack, Discord\n      ],\n    }),\n  ],\n});\n\nconst server = http.createServer(async function (\n  req: http.IncomingMessage,\n  res: http.ServerResponse,\n) {\n  const decision = await aj.protect(req);\n  console.log(\"Arcjet decision\", decision);\n\n  if (decision.isDenied()) {\n    res.writeHead(403, { \"Content-Type\": \"application/json\" });\n    res.end(JSON.stringify({ error: \"Forbidden\" }));\n  } else {\n    res.writeHead(200, { \"Content-Type\": \"application/json\" });\n    res.end(JSON.stringify({ message: \"Hello world\" }));\n  }\n});\n\nserver.listen(8000);\n```\n\n## Packages\n\nWe provide the source code for various packages in this repository, so you can\nfind a specific one through the categories and descriptions below.\n\n### SDKs\n\n- [`@arcjet/bun`](./arcjet-bun/README.md): SDK for Bun.sh.\n- [`@arcjet/deno`](./arcjet-deno/README.md): SDK for Deno.\n- [`@arcjet/fastify`](./arcjet-fastify/README.md): SDK for Fastify.\n- [`@arcjet/nest`](./arcjet-nest/README.md): SDK for NestJS.\n- [`@arcjet/next`](./arcjet-next/README.md): SDK for Next.js.\n- [`@arcjet/node`](./arcjet-node/README.md): SDK for Node.js.\n- [`@arcjet/react-router`](./arcjet-react-router/README.md): SDK for React Router.\n- [`@arcjet/remix`](./arcjet-remix/README.md): SDK for Remix.\n- [`@arcjet/sveltekit`](./arcjet-sveltekit/README.md): SDK for SvelteKit.\n\n### Analysis\n\n- [`@arcjet/analyze`](./analyze/README.md): Local analysis engine.\n- [`@arcjet/headers`](./headers/README.md): Arcjet extension of the Headers\n  class.\n- [`@arcjet/ip`](./ip/README.md): Utilities for finding the originating IP of a\n  request.\n- [`@arcjet/redact`](./redact/README.md): Redact \u0026 unredact sensitive\n  information from strings.\n\n### Nosecone\n\nSee [the docs][nosecone-docs] for details.\n\n- [`nosecone`](./nosecone/README.md): Protect your `Response` with secure\n  headers.\n- [`@nosecone/next`](./nosecone-next/README.md): Protect your Next.js\n  application with secure headers.\n- [`@nosecone/sveltekit`](./nosecone-sveltekit/README.md): Protect your\n  SvelteKit application with secure headers.\n\n### Utilities\n\n- [`arcjet`](./arcjet/README.md): JS SDK core.\n- [`@arcjet/body`](./body/README.md): utilities for extracting the body from a\n  Node.js IncomingMessage.\n- [`@arcjet/cache`](./cache/README.md): Interface and implementations for value\n  caches.\n- [`@arcjet/decorate`](./decorate/README.md): Utilities for decorating responses\n  with information.\n- [`@arcjet/duration`](./duration/README.md): Utilities for parsing duration\n  strings into seconds integers.\n- [`@arcjet/env`](./env/README.md): Environment detection for Arcjet variables.\n- [`@arcjet/inspect`](./inspect/README.md): Utilities for inspecting decisions\n  made by an SDK.\n- [`@arcjet/logger`](./logger/README.md): Lightweight logger which mirrors the\n  Pino structured logger interface.\n- [`@arcjet/protocol`](./protocol/README.md): JS interface into the Arcjet\n  protocol.\n- [`@arcjet/runtime`](./runtime/README.md): Runtime detection.\n- [`@arcjet/sprintf`](./sprintf/README.md): Platform-independent replacement for\n  `util.format`.\n- [`@arcjet/transport`](./transport/README.md): Transport mechanisms for the\n  Arcjet protocol.\n\n### Internal development\n\n- [`@arcjet/eslint-config`](./eslint-config/README.md): Custom eslint config for\n  our projects.\n- [`@arcjet/redact-wasm`](./redact-wasm/README.md): Sensitive information\n  redaction detection engine.\n- [`@arcjet/rollup-config`](./rollup-config/README.md): Custom rollup config for\n  our projects.\n\n## Support\n\nThis repository follows the [Arcjet Support Policy][arcjet-support].\n\n## Security\n\nThis repository follows the [Arcjet Security Policy][arcjet-security].\n\n## Compatibility\n\nPackages maintained in this repository are compatible with maintained\nversions of Node.js and the current minor release of TypeScript.\n\nThe current release line,\n`@arcjet/*` on `1.0.0-beta.*`,\nis compatible with Node.js 18.\n\n## License\n\nLicensed under the [Apache License, Version 2.0][apache-license].\n\n[arcjet-example]: https://example.arcjet.com\n[arcjet]: https://arcjet.com\n[file-examples]: ./examples/\n[github-arcjet-example-astro]: https://github.com/arcjet/example-astro\n[github-arcjet-example-express]: https://github.com/arcjet/example-expressjs\n[github-arcjet-example-fastify]: https://github.com/arcjet/example-fastify\n[github-arcjet-example-nestjs]: https://github.com/arcjet/example-nestjs\n[github-arcjet-example-nextjs-bot-protection]: https://github.com/arcjet/example-nextjs-bot-protection\n[github-arcjet-example-nextjs-server-action]: https://github.com/arcjet/example-nextjs-server-action\n[github-arcjet-example-nextjs-form]: https://github.com/arcjet/example-nextjs-form\n[github-arcjet-example-nextjs]: https://github.com/arcjet/example-nextjs\n[github-arcjet-example-remix]: https://github.com/arcjet/example-remix\n[github-arcjet-example-tanstack-start]: https://github.com/arcjet/example-tanstack-start\n[discord-invite]: https://arcjet.com/discord\n[support]: https://docs.arcjet.com/support\n[bot-protection-concepts-docs]: https://docs.arcjet.com/bot-protection/concepts\n[arcjet-docs]: https://docs.arcjet.com/\n[arcjet-support]: https://docs.arcjet.com/support\n[arcjet-security]: https://docs.arcjet.com/security\n[apache-license]: http://www.apache.org/licenses/LICENSE-2.0\n[nosecone-docs]: https://docs.arcjet.com/nosecone/quick-start\n[blueprint-ai-quota-control]: https://docs.arcjet.com/blueprints/ai-quota-control\n[blueprint-ip-geolocation]: https://docs.arcjet.com/blueprints/ip-geolocation\n[blueprint-cookie-banner]: https://docs.arcjet.com/blueprints/cookie-banner\n[blueprint-payment-form-protection]: https://docs.arcjet.com/blueprints/payment-form\n[blueprint-vpn-proxy-detection]: https://docs.arcjet.com/blueprints/vpn-proxy-detection\n[bot-protection-quick-start]: https://docs.arcjet.com/bot-protection/quick-start\n[rate-limiting-quick-start]: https://docs.arcjet.com/rate-limiting/quick-start\n[shield-quick-start]: https://docs.arcjet.com/shield/quick-start\n[email-validation-quick-start]: https://docs.arcjet.com/email-validation/quick-start\n[signup-protection-quick-start]: https://docs.arcjet.com/signup-protection/quick-start\n[sensitive-info-quick-start]: https://docs.arcjet.com/sensitive-info/quick-start\n[nosecone-quick-start]: https://docs.arcjet.com/nosecone/quick-start\n[quick-start-astro]: https://docs.arcjet.com/get-started?f=astro\n[quick-start-bun-hono]: https://docs.arcjet.com/get-started?f=bun-hono\n[quick-start-bun]: https://docs.arcjet.com/get-started?f=bun\n[quick-start-deno]: https://docs.arcjet.com/get-started?f=deno\n[quick-start-fastify]: https://docs.arcjet.com/get-started?f=fastify\n[quick-start-nest-js]: https://docs.arcjet.com/get-started?f=nest-js\n[quick-start-next-js]: https://docs.arcjet.com/get-started?f=next-js\n[quick-start-node-js-express]: https://docs.arcjet.com/get-started?f=node-js-express\n[quick-start-node-js-hono]: https://docs.arcjet.com/get-started?f=node-js-hono\n[quick-start-node-js]: https://docs.arcjet.com/get-started?f=node-js\n[quick-start-remix]: https://docs.arcjet.com/get-started?f=remix\n[quick-start-sveltekit]: https://docs.arcjet.com/get-started?f=sveltekit\n","funding_links":[],"categories":["TypeScript","webassembly"],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Farcjet%2Farcjet-js","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Farcjet%2Farcjet-js","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Farcjet%2Farcjet-js/lists"}