diff --git a/info/pricing.mdx b/info/pricing.mdx
index 34b28f1..ef5254a 100644
--- a/info/pricing.mdx
+++ b/info/pricing.mdx
@@ -4,14 +4,24 @@ title: "Pricing & Limits"
With Kernel, you only pay for what you use and nothing more. You don't pay for idle time thanks to [Standby Mode](/browsers/standby), and you're never charged for proxies. Our goal is to be cost-effective, scalable, and transparent.
+## Pricing
+
+| Browser type | Memory | Price ($/sec) |
+| --- | --- | --- |
+| Headless | 1 GB | 0.0000166667 |
+| Headful | 8 GB | 0.0001333336 |
+
+### Pricing calculator
+
+import { PricingCalculator } from '/snippets/calculator.jsx';
+
+
+
## Managed infrastructure
| Feature | Developer (free + usage) | Hobbyist ($30 / mo + usage) | Start-Up ($200 / mo + usage) | Enterprise |
| --- | --- | --- | --- | --- |
-| Price per gb-second ($) | 0.0000166667 | 0.0000166667 | 0.0000166667 | Custom |
-| Headless browsers resource | 1 gb | 1 gb | 1 gb | 1 gb |
-| Headful browsers resource | 8 gb | 8 gb | 8 gb | 8 gb |
-| Free usage credits / mo | $5 | $10 | $50 | Custom |
+| Included credits / mo | $5 | $10 | $50 | Custom |
| Extended browser timeouts | ✅ | ✅ | ✅ | ✅ |
| Browser live view | ✅ | ✅ | ✅ | ✅ |
| Configurable browser viewports | ✅ | ✅ | ✅ | ✅ |
@@ -59,9 +69,3 @@ Auth sessions are fast (typically 5-30 seconds each). Kernel monitors session he
| Managed auth profiles | N/A | 3 | 20 | Custom |
> Note: Limits are org-wide by default unless stated otherwise. `Managed auth profiles` refer to the number of active auth connections that Kernel maintains using your stored [Credentials](/profiles/credentials) or [1Password connection](/integrations/1password).
-
-## Pricing calculator
-
-import { PricingCalculator } from '/snippets/calculator.jsx';
-
-
diff --git a/snippets/calculator.jsx b/snippets/calculator.jsx
index 14e15a3..3ce7bd1 100644
--- a/snippets/calculator.jsx
+++ b/snippets/calculator.jsx
@@ -9,10 +9,30 @@ export const PricingCalculator = () => {
}
const usagePrices = 0.0000166667
- const [plan, setPlan] = useState('free');
- const [headless, setHeadless] = useState(true);
- const [avgSessionLength, setAvgSessionLength] = useState(30);
- const [numSessions, setNumSessions] = useState(100);
+ // Initialize state from URL params
+ const getInitialState = () => {
+ if (typeof window === 'undefined') {
+ return {
+ plan: 'free',
+ headless: true,
+ avgSessionLength: 30,
+ numSessions: 100
+ };
+ }
+ const params = new URLSearchParams(window.location.search);
+ return {
+ plan: params.get('plan') || 'free',
+ headless: params.get('headless') === 'false' ? false : true,
+ avgSessionLength: parseInt(params.get('length')) || 30,
+ numSessions: parseInt(params.get('sessions')) || 100
+ };
+ };
+
+ const initialState = getInitialState();
+ const [plan, setPlan] = useState(initialState.plan);
+ const [headless, setHeadless] = useState(initialState.headless);
+ const [avgSessionLength, setAvgSessionLength] = useState(initialState.avgSessionLength);
+ const [numSessions, setNumSessions] = useState(initialState.numSessions);
const [flash, setFlash] = useState(false);
const prevPriceRef = useRef(null);
@@ -42,6 +62,20 @@ export const PricingCalculator = () => {
}
prevPriceRef.current = { usageCost, includedUsageCredits, price };
}, [usageCost, includedUsageCredits, price]);
+
+ // Update URL params when state changes
+ useEffect(() => {
+ if (typeof window === 'undefined') return;
+
+ const params = new URLSearchParams();
+ params.set('plan', plan);
+ params.set('headless', headless.toString());
+ params.set('length', avgSessionLength.toString());
+ params.set('sessions', numSessions.toString());
+
+ const newUrl = `${window.location.pathname}?${params.toString()}`;
+ window.history.replaceState({}, '', newUrl);
+ }, [plan, headless, avgSessionLength, numSessions]);
const labelStyle = { fontWeight: 600, fontSize: '0.875rem', minWidth: '10rem', flexShrink: 0, maxWidth: '10rem' };
const rowStyle = { display: 'flex', alignItems: 'center', gap: '0.5rem', minHeight: '2.25rem' };
const inputStyle = { minWidth: 0, flex: 1, maxWidth: '100%', boxSizing: 'border-box', background: 'transparent' };