SDK migration
Our philosophy around major SDK version upgrades is to avoid breaking changes where possible. When they are necessary, we deprecate rather than break, and provide a clear migration path that remains supported for some time.
This page documents breaking changes and migrations between SDK releases.
Arcjet JS SDK main
Section titled “Arcjet JS SDK main”The JS SDK on main includes the following breaking changes.
Remove threshold and score from prompt injection detection
Section titled “Remove threshold and score from prompt injection detection”detectPromptInjection({ threshold }) and
ArcjetPromptInjectionReason.score are removed. Only mode remains.
The verdict is binary. Use decision.reason.isPromptInjection() or
decision.reason.injectionDetected:
detectPromptInjection({ mode: "LIVE" });
if (decision.reason.isPromptInjection()) { return new Response("Prompt injection detected", { status: 403 });}Drop threshold and score when you upgrade. The core SDK ignores leftover
threshold – it does not throw and it does not change the rule id.
@arcjet/astro validates rule options with Zod .strict(). Leftover
threshold in the integration config throws at startup. Remove threshold
from astro.config when you upgrade.
This change applies to the JS SDK only.
Arcjet Python SDK main
Section titled “Arcjet Python SDK main”The Python SDK on main includes the following breaking changes.
Remove threshold from prompt injection detection
Section titled “Remove threshold from prompt injection detection”detect_prompt_injection(threshold=...) and the threshold field on
PromptInjectionDetection are removed. Only mode remains, and it is
required.
from arcjet import Mode, detect_prompt_injection
detect_prompt_injection(mode=Mode.LIVE)Drop threshold when you upgrade to Python SDK main. Passing threshold=
raises TypeError. This differs from the JS core SDK, which ignores leftover
threshold and does not throw. @arcjet/astro Zod .strict() throws at
startup if threshold is still in the integration config.
PromptInjectionReason.score remains deprecated. This removal does not drop
score.
Require explicit mode on HTTP rule factories
Section titled “Require explicit mode on HTTP rule factories”HTTP Protect rule factories require mode. Omitting it raises TypeError.
Pass mode on every shield(), detect_bot(), token_bucket(),
fixed_window(), sliding_window(), validate_email(),
detect_sensitive_info(), filter_request(), and
detect_prompt_injection() call.
from arcjet import Mode, detect_bot, shield
rules = [ shield(mode=Mode.LIVE), detect_bot(mode=Mode.LIVE, allow=["CATEGORY:SEARCH_ENGINE"]),]protect_signup() forwards its nested rate_limit, bots, and email
mappings to those factories, so each mapping must include mode too.
This differs from JavaScript HTTP rules, which default to "DRY_RUN".
Defaulting Python HTTP rules to DRY_RUN turns LIVE configs into
observe-only. Requiring mode is the breaking change.
Guard constructors still default to Mode.LIVE, matching the JavaScript
Guard SDK. You can omit mode on Guard constructors.
These changes are on Python SDK main, not in published arcjet 0.9.0 or
0.10.0b1.
Arcjet JS SDK 1.0.0 – 1.4.0
Section titled “Arcjet JS SDK 1.0.0 – 1.4.0”There have been no breaking changes.
Arcjet JS SDK 1.0.0
Section titled “Arcjet JS SDK 1.0.0”The
1.0.0
version of the Arcjet JS SDK was released on January 22, 2026. No migrations are required from the last 1.0.0-beta-18 release.
Arcjet JS SDK 1.0.0 beta 18
Section titled “Arcjet JS SDK 1.0.0 beta 18”The
1.0.0-beta-18
version of the Arcjet JS SDK was released on January 22, 2026 and includes the
following breaking changes.
Deprecate automatic body reading
Section titled “Deprecate automatic body reading”Reading streams has various pitfalls. You can now pass what value to check explicitly:
const decision = await arcjet.protect(request, { sensitiveInfoValue: "..." });This value is processed locally and is not sent to the Arcjet cloud API.
If you use tools that patch request.body, such as body-parser, you are not affected and can continue to use them.
Arcjet JS SDK 1.0.0 beta 17
Section titled “Arcjet JS SDK 1.0.0 beta 17”The
1.0.0-beta-17
version of the Arcjet JS SDK was released on January 13, 2026 and includes the
following breaking changes.
Remove block field in validateEmail rule config
Section titled “Remove block field in validateEmail rule config”This field was deprecated in
1.0.0-beta-1
in favor of deny:
validateEmail({ deny: ["DISPOSABLE"], mode: "LIVE" });Arcjet JS SDK 1.0.0 beta 1
Section titled “Arcjet JS SDK 1.0.0 beta 1”The
1.0.0-beta-1
version of the Arcjet JS SDK was released on January 15, 2025 and includes the
following breaking changes.
block is now deny for validateEmail rules
Section titled “block is now deny for validateEmail rules”When configuring the validateEmail rule we have renamed the block option to
deny. This follows the same API design as the other rules.
validateEmail({ mode: "LIVE", // replace block with deny as shown // block: ["DISPOSABLE"], deny: ["DISPOSABLE"],});It is now also possible to configure email types to allow. In the following example, Arcjet allows only email addresses from free email providers.
validateEmail({ mode: "LIVE", allow: ["FREE"],});The old options continue to work, but are flagged as deprecated.
ArcjetEnum objects are now deprecated
Section titled “ArcjetEnum objects are now deprecated”In earlier versions of the SDK we provided enum objects for configuring your rules. These have been deprecated in favor of string-type enums.
The following table shows which enums to replace and their equivalent strings.
| alpha | beta |
|---|---|
ArcjetMode.LIVE | "LIVE" |
ArcjetMode.DRY_RUN | "DRY_RUN" |
ArcjetRateLimitAlgorithm.TOKEN_BUCKET | "TOKEN_BUCKET" |
ArcjetRateLimitAlgorithm.FIXED_WINDOW | "FIXED_WINDOW" |
ArcjetRateLimitAlgorithm.SLIDING_WINDOW | "SLIDING_WINDOW" |
ArcjetEmailType.DISPOSABLE | "DISPOSABLE" |
ArcjetEmailType.FREE | "FREE" |
ArcjetEmailType.NO_MX_RECORDS | "NO_MX_RECORDS" |
ArcjetEmailType.NO_GRAVATAR | "NO_GRAVATAR" |
ArcjetEmailType.INVALID | "INVALID" |
ArcjetStack.NODEJS | "NODEJS" |
ArcjetStack.NEXTJS | "NEXTJS" |
ArcjetStack.BUN | "BUN" |
ArcjetStack.SVELTEKIT | "SVELTEKIT" |
ArcjetStack.DENO | "DENO" |
ArcjetStack.NESTJS | "NESTJS" |
ArcjetStack.REMIX | "REMIX" |
ArcjetRuleState.RUN | "RUN" |
ArcjetRuleState.NOT_RUN | "NOT_RUN" |
ArcjetRuleState.CACHED | "CACHED" |
ArcjetRuleState.DRY_RUN | "DRY_RUN" |
ArcjetConclusion.ALLOW | "ALLOW" |
ArcjetConclusion.DENY | "DENY" |
ArcjetConclusion.CHALLENGE | "CHALLENGE" |
ArcjetConclusion.ERROR | "ERROR" |
ArcjetSensitiveInfoType.EMAIL | "EMAIL" |
ArcjetSensitiveInfoType.PHONE_NUMBER | "PHONE_NUMBER" |
ArcjetSensitiveInfoType.IP_ADDRESS | "IP_ADDRESS" |
ArcjetSensitiveInfoType.CREDIT_CARD_NUMBER | "CREDIT_CARD_NUMBER" |
ArcjetRuleType.LOCAL | "LOCAL" |
ArcjetRuleType.REMOTE | "REMOTE" |
URL-encoded data in sensitive info detection
Section titled “URL-encoded data in sensitive info detection”Arcjet Sensitive info detection and
@arcjet/redact features
handle both raw and URL-encoded data simultaneously. This dual processing
approach improves detection, particularly for content containing
the + character, which serves both as a literal plus sign (common in phone
numbers) and as an encoded space in URLs.
When implementing custom detection functions on data containing + characters, you may observe duplicate token matches across different processing windows. This occurs because the system analyzes the input in two ways:
- With
+interpreted as a literal plus sign - With
+decoded as a space character
For example:
# Input: "phone+number+123"# Processed as both:# - "phone+number+123"# - "phone number 123"Wasm loading has moved to @arcjet/analyze-wasm
Section titled “Wasm loading has moved to @arcjet/analyze-wasm”We have moved the responsibility for loading Wasm on your target platform from
@arcjet/analyze to @arcjet/analyze-wasm. This does not affect users who were
using the SDK through the high level framework adapters, such as @arcjet/next.
Arcjet JS SDK 1.0.0-alpha.24
Section titled “Arcjet JS SDK 1.0.0-alpha.24”The
1.0.0-alpha-24
version of the Arcjet JS SDK was released on September 5, 2024 and includes the
following breaking changes.
add and remove replaced with allow and deny in detectBot rule
Section titled “add and remove replaced with allow and deny in detectBot rule”Passing user agent patterns to the bot detection rules has been deprecated in
favor of specifying string-type enums to allow or deny.
To maintain the previous default behavior of denying all bots, you can configure the following rule:
detectBot({ mode: "LIVE", allow: [],});We now publish a list of known bots as both individual user agents as well as categories of types of bots. You can use these to configure your bot detection rules.
For example, a common configuration is to block all bots except search engine crawlers:
detectBot({ mode: "LIVE", // Block all bots except the following allow: [ "CATEGORY:SEARCH_ENGINE", // Google, Bing, etc // Uncomment to allow these other common bot categories // See the full list at https://arcjet.com/bot-list //"CATEGORY:MONITOR", // Uptime monitoring services //"CATEGORY:PREVIEW", // Link previews e.g. Slack, Discord ],}),Get help
Section titled “Get help”Need help with anything? Email us or join our Discord to get support from our engineering team.