~/cron ☀ LIGHT 🔍 regex 🌐 subnet 🕑 clocks ☕ Support me apps ← about me
// crontab · kubernetes · quartz · spring · aws · azure · jenkins · github · systemd

What Is a Cron Expression? Explainer, Syntax & Next Run Times

What is a cron expression?

A cron expression is a short line of five fields — minute, hour, day of month, month and day of week — that tells a scheduler when to run a job. Each field holds a number, a list, a range or * for “every”, so 0 9 * * 1-5 means 09:00 on every weekday. Cron runs the command whenever the current time matches all five fields.

┌───────────── minute        (0–59)
│ ┌─────────── hour          (0–23)
│ │ ┌───────── day of month  (1–31)
│ │ │ ┌─────── month         (1–12)
│ │ │ │ ┌───── day of week   (0–6, Sunday = 0)
│ │ │ │ │
* * * * *  command to run

*/5 9-17 * * 1-5  → every 5 min, 09:00–17:55, Mon–Fri
ExpressionRuns
* * * * *every minute
*/5 * * * *every 5 minutes
0 * * * *every hour, on the hour
0 0 * * *every day at midnight
0 9 * * 1-509:00 on weekdays
0 0 1 * *first day of every month

* any value  ·  , list (1,15)  ·  - range (1-5)  ·  / step (*/10).  Some platforms add a seconds or year field — see the common schedules or paste your own below.

Paste a cron expression and read it back in plain English, with the next 12 run times in whatever timezone you actually care about. The catch nobody warns you about is that “cron” is not one language. 0 0 * * 1 means Monday on Linux and Sunday in Quartz. A five-field string is a syntax error to Spring. ? is mandatory on AWS and meaningless on a server. So this tool parses against the platform you pick — and then shows you what the same string would do on the other seven.

Which scheduler is this for?
// common cron expressions — click to load
// how often it fires, and how far apart
minute(s), can the next one start on top of it?
// the coming week, hour by hour
// the next clock changes in this timezone
// the same string on every other scheduler — click one to switch
// the same schedule, written for every other scheduler
// ready to paste — with the locking, logging and timezone people forget
// paste a whole crontab and have every line explained
▸ Nothing leaves your browser. The parser, the schedule maths and the timezone conversions all run in this page. There is no request to any server — you can read the source, or disconnect and it still works.

Guide — read any cron expression in five steps

From a string you found in a config file to knowing exactly when it runs, on which platform, in which timezone.
1Pick the scheduler

Unix crontab, Kubernetes, Quartz, Spring, AWS EventBridge, Azure, Jenkins or GitHub Actions. Field count and day numbering differ, so this decides how the string is read.

2Paste the expression

It is read back in plain English as you type, and a syntax error names the field it came from. No expression yet? Type it in words or use the builder.

3Set the timezone

Choose the zone the scheduler runs in. The next 12 runs show in that zone with the UTC instant alongside.

4Read the warnings

The OR rule between the two day fields, uneven steps such as */7, months without the chosen day, and runs that daylight saving skips or repeats.

5Compare and copy

See what the same string does on the other seven schedulers, copy the converted version, or grab a ready-made crontab line with locking and logging.

Which panel answers which question

READWhat does it mean?
verdict
the expression in one plain-English sentence
fields
minute, hour, day, month, weekday labelled
examples
common schedules, one click to load
WHENWhen does it actually run?
next runs
the next 12, in your zone and UTC
week grid
the coming week, hour by hour
clock changes
the next DST jumps and what they do
WHEREDoes it work on my platform?
cross-check
the same string on all eight schedulers
convert
rewritten for each, incl. systemd
SHIPIs my crontab safe?
snippets
lines with flock, logging and TZ=
audit
paste a crontab, every line explained
overlap
can the next run start on top of the last?

Common cron schedules — the ones people look up

Every line here is a working expression in standard five-field cron. Click use to load one into the parser above and see its next runs in your timezone; the URL updates, so the result is shareable.

Every few minutes
* * * * *Every minute
*/2 * * * *Every 2 minutes
*/3 * * * *Every 3 minutes
*/5 * * * *Every 5 minutes
*/10 * * * *Every 10 minutes
*/15 * * * *Every 15 minutes (quarter past, half past, quarter to, on the hour)
*/20 * * * *Every 20 minutes
*/30 * * * *Every 30 minutes
0,30 * * * *Twice an hour — on the hour and at half past
5 * * * *At five past every hour
*/5 9-17 * * 1-5Every 5 minutes during office hours, weekdays only
Hourly
0 * * * *Every hour, on the hour
0 */2 * * *Every 2 hours
0 */3 * * *Every 3 hours
0 */4 * * *Every 4 hours
0 */6 * * *Every 6 hours — 00:00, 06:00, 12:00, 18:00
0 */8 * * *Every 8 hours
0 */12 * * *Every 12 hours
0 9-17 * * *Every hour between 09:00 and 17:00
0 9-17/2 * * 1-5Every 2 hours during the working day, weekdays
30 */6 * * *At half past, every 6 hours
Daily
0 0 * * *Every day at midnight
0 1 * * *Every day at 01:00
0 2 * * *Every day at 02:00 — the usual slot for backups
30 2 * * *Every day at 02:30
0 3 * * *Every day at 03:00
0 6 * * *Every day at 06:00
0 8 * * *Every day at 08:00
0 9 * * *Every day at 09:00
0 12 * * *Every day at noon
0 17 * * *Every day at 17:00
0 18 * * *Every day at 18:00
0 22 * * *Every day at 22:00
0 0,12 * * *Twice a day — midnight and noon
15 14 * * *Every day at 14:15
Weekly and weekdays
0 9 * * 1-5Weekdays at 09:00
0 18 * * 1-5Weekdays at 18:00
*/30 9-17 * * 1-5Every half hour during office hours, weekdays
0 0 * * 0Every Sunday at midnight
0 0 * * 1Every Monday at midnight
0 9 * * 1Every Monday at 09:00 — the weekly report slot
0 9 * * 2Every Tuesday at 09:00
0 9 * * 3Every Wednesday at 09:00
0 9 * * 4Every Thursday at 09:00
0 17 * * 5Every Friday at 17:00
0 0 * * 6Every Saturday at midnight
0 0 * * 6,0Weekends at midnight
0 3 * * 0Sunday at 03:00 — the weekly maintenance window
Monthly and yearly
0 0 1 * *The 1st of every month at midnight
0 6 1 * *The 1st of every month at 06:00
0 0 1,15 * *The 1st and the 15th
0 0 15 * *The 15th of every month
0 4 8-14 * 0The first Sunday of the month — the standard Unix idiom
0 4 1-7 * 1The first Monday of the month (same idiom)
0 0 L * *The last day of the month — Quartz and AWS only
0 0 1 */3 *The first day of every quarter
0 0 1 1,4,7,10 *Quarterly, written out — January, April, July, October
0 0 1 */6 *Twice a year
0 0 1 1 *Once a year, on 1 January
0 0 25 12 *Once a year, on 25 December
Macros and special cases
@hourlyShorthand for 0 * * * *
@dailyShorthand for 0 0 * * * (also @midnight)
@weeklyShorthand for 0 0 * * 0
@monthlyShorthand for 0 0 1 * *
@yearlyShorthand for 0 0 1 1 * (also @annually)
@rebootOnce, when the machine boots — not a schedule at all
0 0 29 2 *29 February — runs only in leap years
0 0 31 * *The 31st — which seven months of the year actually have
0 0 13 * 5The OR trap: every 13th AND every Friday, not Friday the 13th

When a cron job silently does not run

Cron almost never tells you that something failed. It has no log of its own beyond a line saying it started the command, it mails output to an address that usually goes nowhere, and a schedule that can never match is not an error. These are the causes, in the order they actually happen:

SymptomUsual causeFix
Works in the shell, not in cronMinimal PATH and no profileAbsolute paths, or PATH= at the top of the crontab
Nothing in any logOutput was mailed and dropped>> /var/log/job.log 2>&1
Runs an hour early or late twice a yearDaylight savingRun in UTC, or avoid 01:00–03:00 local
Runs far more often than intendedBoth day fields set — the OR ruleLeave one of them *
Command stops at a percent sign% is a newline in crontabsEscape it as \%
Skipped every time the machine sleepsCron does not catch upsystemd timer with Persistent=true, or anacron
Several copies running at onceA run overran its intervalflock -n, or concurrencyPolicy: Forbid
Nothing at all, on a fresh fileMissing trailing newlineEnd the crontab with a blank line

The audit box on this page checks a pasted crontab for most of these — the unescaped %, the missing redirect, relative command paths with no PATH, duplicate lines and midnight pile-ups — and shows the next run time for every line so you can see at a glance which ones are dead.

cron, systemd timers, and which one to reach for

A timer unit is two files where cron is one line, and it buys three things cron cannot do at any price:

Cron still wins on portability — every Unix has it, containers ship it, and a single line in a file is hard to beat for something trivial. The conversion panel above turns whatever you have typed into an OnCalendar= line, with one honest caveat: cron treats day-of-month and day-of-week as an or, systemd treats them as an and, so a schedule that uses both fields fires on fewer days as a timer than it does as a crontab line.

The five fields, and the sixth that catches people out

A classic crontab line is five fields separated by spaces, and they are always in this order:

PositionFieldRangeNotes
1minute0–59
2hour0–2324-hour clock, no AM/PM
3day of month1–31see the OR trap below
4month1–12 or JAN–DEC
5day of week0–7 or SUN–SAT0 and 7 are both Sunday

Four characters do all the work. * means every value. , lists them (1,15). - is a range (9-17). / is a step, so */15 is every fifteenth. That is the entire language — everything else is a platform extension.

The sixth field is where it goes wrong. Quartz, Spring and Azure Functions put seconds first, so their expressions have six fields and everything shifts one place right. AWS EventBridge also uses six, but its extra field is a year on the end, not seconds at the front. Paste a five-field line into any of them and you get either a rejection or, worse, a schedule that runs sixty times more often than you meant. That is why this page asks which scheduler you are targeting before it tells you anything.

Day-of-month and day-of-week are an OR, not an AND

This is the single most expensive misunderstanding in cron, and it is genuinely counter-intuitive. In standard Vixie cron — Linux, Kubernetes, Jenkins, GitHub Actions — when both the day-of-month and day-of-week fields are restricted, the job runs when either one matches.

So 0 0 13 * 5 is not “midnight on Friday the 13th”. It is midnight on every 13th, and also midnight every Friday — about 60 runs a year instead of one or two. People discover this when a monthly report starts arriving weekly.

The rule only applies when both fields are restricted. If either is *, the other simply wins, which is why 0 0 * * 5 (every Friday) and 0 0 13 * * (every 13th) both behave exactly as you would expect.

There is no way to express a true AND in standard cron. The usual workaround is to schedule the broader of the two and test the date inside the job:

0 0 13 * * [ "$(date +\%u)" = "5" ] && /path/to/job

Quartz and AWS EventBridge dodge the problem entirely by making you write ? in whichever day field you are not using, so only one of them is ever active. This tool warns you the moment both fields are set on a dialect where the OR applies.

Timezones and daylight saving break more cron jobs than syntax errors do

Cron schedules wall-clock time, not elapsed time. It looks at the clock on the wall, and if the clock says the job is due, it runs. Twice a year that clock does something strange, and two predictable failures follow.

Spring forward: the run that never happens

When clocks jump from 02:00 to 03:00, the hour in between does not exist. A job scheduled for 30 2 * * * is simply skipped that day — no error, no log line, no alert. If that job was your nightly backup, you have a hole in your backups exactly once a year, and nothing tells you.

Fall back: the run that happens twice

When clocks go from 03:00 back to 02:00, the 02:00–03:00 hour is replayed. That same job runs twice, roughly an hour apart. If it is not idempotent — a billing run, an email send, a counter increment — you have just done it to every customer twice.

The run list on this page flags both cases explicitly, marking skipped runs and repeated hours against whichever timezone you select. The practical fix is to avoid scheduling anything between 01:00 and 03:00 local time, or to run in UTC, which has no daylight saving at all. Running in UTC means your “9am job” drifts an hour twice a year relative to office hours — usually the lesser evil, and always the more predictable one.

Where the timezone comes from also varies. A Linux crontab uses the server timezone, or a TZ= line at the top of the file. A Kubernetes CronJob is UTC unless you set spec.timeZone, which only exists from 1.27. AWS EventBridge cron() rules are UTC with no option at all. GitHub Actions is UTC, always.

The same string means different things on different platforms

Eight schedulers, eight sets of rules. These are the differences that actually change what runs when:

PlatformFieldsSunday isSeconds?L / W / #
Unix / crontab50 or 7nonono
Kubernetes CronJob50 or 7nonono
Quartz6 or 71yes, firstrequiredyes
Spring @Scheduled60 or 7yes, firstallowedno
AWS EventBridge61no (year last)requiredyes
Azure NCRONTAB60yes, firstnono
Jenkins50 or 7nonono (has H)
GitHub Actions50 or 7nonono

The day numbering is the dangerous one, because a Quartz expression copied from a Linux crontab is still valid — it just runs a day early, every time, for ever. In Quartz and AWS, Sunday is 1 and Saturday is 7. Everywhere else Sunday is 0. So 1 means Monday on your server and Sunday in your Java scheduler, and nothing will ever tell you.

The comparison panel above the examples shows, for whatever you have typed, which of the eight accept it and which of those give it a different meaning. If you are migrating a schedule between platforms, that panel is the whole reason this page exists.

Steps, ranges and the ones that quietly misfire

*/n reads as “every n”, and mostly behaves — but only when n divides the field range evenly. */15 in the minute field gives you 0, 15, 30, 45 and then wraps cleanly. */7 gives you 0, 7, 14, 21, 28, 35, 42, 49, 56 — and then the next run is 0, which is four minutes later, not seven. Every hour has one short gap. The same applies to */7 in hours, */45 in minutes, and anything else that does not divide its range.

A step can also start somewhere other than zero: 5/10 means “from 5, every 10” — 5, 15, 25, 35, 45, 55. And a range can carry a step, so 0-30/5 is every five minutes for the first half hour only.

Days that do not exist

0 0 31 * * looks monthly but runs seven times a year, because April, June, September and November have no 31st. 0 0 30 2 * parses perfectly and can never run. If you want the last day of the month on Linux there is no L — the idiom is to run on the 1st and subtract a day, or to check inside the job with [ "$(date -d tomorrow +\%d)" = "01" ]. On Quartz and AWS you can simply write L.

This page flags all of these as you type, along with the frequency: if an expression fires 1,440 times a day it will tell you, because a job that runs every minute and sometimes takes 70 seconds will happily start overlapping copies of itself until the box falls over. flock, a lock file, or concurrencyPolicy: Forbid on Kubernetes.

How to read and write a cron expression

A cron expression is five fields — minute, hour, day of month, month, day of week — that tell a scheduler when to run a job. The explainer above reads any expression back in plain English; the sections below cover the questions that come up once you start writing them yourself.

Cron, a cron job and a crontab

Cron is the background service (daemon) on Linux and macOS that runs scheduled commands. A cron job is one scheduled command. The crontab (cron table) is the file that lists your cron jobs, one per line: a cron expression followed by the command.

Edit it with crontab -e and list it with crontab -l.

How many fields: five, six or seven

Standard Unix cron and Kubernetes use five: minute, hour, day of month, month, day of week. Quartz and Spring add seconds at the start (six), Quartz allows an optional year at the end (seven), and AWS EventBridge uses six fields with a year and needs ? in one of the day fields.

How to read a cron expression

Read it left to right as minute, hour, day of month, month, day of week. 30 4 * * 1 is: minute 30, hour 4, any day of the month, any month, day-of-week 1 — so 04:30 every Monday.

The trick is that the fields you leave as * are the ones that set the frequency. A * in the day-of-month and month fields means “daily”; putting a number in the day-of-week field narrows it to weekly. Paste any expression into the box above and it will read it out for you.

What * * * * * means

Every minute of every hour of every day — 1,440 runs a day, 10,080 a week. It is the most frequent schedule plain cron can express, since the smallest unit is one minute.

If a run can ever take longer than sixty seconds, cron starts the next one anyway and they overlap. Wrap the command in flock -n /tmp/job.lock, or set concurrencyPolicy: Forbid on a Kubernetes CronJob.

How to run a cron job every 5 minutes

*/5 * * * *. The */5 in the minute field means “every fifth minute” — 0, 5, 10, 15 and so on. The four *s after it mean every hour, every day, every month, every weekday.

The same pattern gives you the rest: */10, */15, */30. Only use divisors of 60, or the wrap-around gap will be shorter than the interval — see the warning this tool shows for */7.

How to run a job at a specific time every day

Put the minute and hour in the first two fields and leave the rest as *. 30 3 * * * is 03:30 daily. The hour is a 24-hour clock, so 6pm is 18, not 6.

For several times a day, list them: 0 9,13,17 * * * runs at 09:00, 13:00 and 17:00. For a window, use a range: 0 9-17 * * * is hourly through office hours.

*/5 versus 5

5 means exactly the value 5 — minute 5, once an hour. */5 means every fifth value — minutes 0, 5, 10, 15… twelve times an hour. One character, twelve times the load.

There is also 5/10, which is “start at 5, then every 10”, giving 5, 15, 25, 35, 45, 55.

Is Sunday 0 or 1 in cron?

It depends on the scheduler, and this is the difference most likely to cost you a day.

So 0 0 * * 1 is Monday on a server and Sunday in Quartz. Using the three-letter names — MON, FRI — sidesteps the whole problem, and every dialect here accepts them.

First Monday of the month

On Quartz or AWS EventBridge there is direct syntax: 2#1 in the day-of-week field means “the first Monday” (remember Sunday is 1 there, so Monday is 2). The full Quartz expression is 0 0 9 ? * 2#1.

On Linux there is no #, so the idiom is to combine a day-of-month range with a weekday: 0 9 1-7 * 1 — but remember the OR rule makes that “days 1–7 or any Monday”, which is wrong. The correct version tests inside the job: 0 9 1-7 * * [ "$(date +\%u)" = "1" ] && /path/to/job.

Last day of the month

In Quartz and AWS EventBridge, use L in the day-of-month field. In plain Unix cron there is no such thing, and the idiom is to run every day late in the month and let the job decide: 0 23 28-31 * * [ "$(date -d tomorrow +\%d)" = "01" ] && /path/to/job. The same trick handles “last Friday” and similar rules that cron cannot express — schedule the superset, test the exact condition inside the job.

Which timezone cron uses

Whatever the machine or service is configured for, and it differs by platform:

Pick a zone in the selector above and the run list is recalculated in it, with the UTC instant shown alongside so you can check what the server will actually see.

Should cron jobs run in UTC?

Usually yes, for anything machine-facing. UTC has no daylight saving, so every day is exactly 24 hours and every schedule is exactly as frequent as it looks. Logs from different regions line up. Nothing runs twice, and nothing is skipped.

The cost is that a UTC job drifts an hour relative to local office hours twice a year. For a nightly batch nobody notices; for “email the team at 9am” it matters, and that is the case where a real timezone earns its complexity.

AWS EventBridge cron expressions

When an expression that works on Linux fails in EventBridge, there are three likely reasons. Field count: EventBridge wants six fields, with a year at the end — 0 12 * * ? *, not 0 12 * * *. The question mark: exactly one of day-of-month and day-of-week must be ?; * * in both is rejected outright. Day numbering: Sunday is 1, not 0.

Also worth knowing: EventBridge cron() rules are always UTC, and the minimum resolution is one minute. Select AWS EventBridge above and this page will validate against exactly those rules.

The question mark ?

It means “no specific value” and it exists only to resolve the day-of-month versus day-of-week ambiguity. In Quartz and AWS EventBridge you must put ? in whichever of the two day fields you are not using, so only one is ever active — which is how those platforms avoid the OR trap that catches people on Linux.

Standard Unix cron does not understand ? at all. Paste one into a crontab and the line is rejected.

Kubernetes CronJob schedules

Kubernetes uses the crontab syntax — five fields, Vixie syntax, and the @daily-style macros all work. The differences are operational rather than syntactic:

GitHub Actions schedules that run late

Scheduled runs are best-effort, and GitHub documents this. Scheduled workflows go into a shared queue; at times of high load, the top of the hour especially, they start late and some queued runs are dropped. Scheduling at an odd minute such as 17 * * * * helps.

Two more rules catch people: the shortest interval is once every five minutes, and in public repositories scheduled workflows are disabled automatically after 60 days without repository activity. If a job must happen on time, trigger it from something that guarantees delivery and use Actions only as the runner.

@daily, @hourly and @reboot

They are shorthand macros:

MacroEquivalentMeaning
@yearly / @annually0 0 1 1 *midnight, 1 January
@monthly0 0 1 * *midnight on the 1st
@weekly0 0 * * 0midnight on Sunday
@daily / @midnight0 0 * * *every midnight
@hourly0 * * * *every hour, on the hour
@reboot—once, at startup

@reboot is the odd one out: it has no schedule at all, and it is not supported on Kubernetes, AWS, Azure or GitHub Actions. Nor are the other macros, on AWS and GitHub.

L, W and #

Quartz extensions, also supported by AWS EventBridge, and unavailable everywhere else.

None of these exist in standard cron. Select Quartz or AWS above to use them and see the real dates they resolve to.

Every 30 seconds, or every second

Standard cron cannot do it: one minute is the floor, because there is no seconds field. Schedulers that do have one are Quartz, Spring @Scheduled and Azure NCRONTAB, all of which put seconds first: */30 * * * * * is every thirty seconds in Spring.

On a plain server the usual workaround is a one-minute job that loops internally with sleep, or a systemd timer with OnUnitActiveSec, which handles sub-minute intervals properly and logs its runs.

For a job every 30 seconds there are three honest options: schedule it every minute and have the script sleep 30 and run again; use a systemd timer with OnUnitActiveSec=30s; or use a scheduler that has a seconds field, which means Quartz, Spring or Azure Functions. The sleep trick is fine for something trivial and terrible for anything that can overrun, because now two copies can overlap inside the same minute.

Works in the shell, not in cron

Your shell is not cron's shell. An interactive login reads /etc/profile, ~/.bashrc and ~/.profile; cron reads none of them. You get /bin/sh, a PATH of roughly /usr/bin:/bin, no aliases, no virtualenv, no nvm, no SSH agent and no HOME-relative assumptions. The fix is to make the job self-contained: absolute paths to every binary, explicit environment variables in the crontab or sourced at the top of the script, and a cd into the working directory rather than relying on where cron starts you. Test it the way cron will run it: env -i /bin/sh -c '/path/to/job.sh'.

Missed runs are not caught up

Cron looks at the clock, and if the machine was asleep when the minute passed, that run simply never happened. This is what anacron was invented for on laptops and desktops, and what systemd timers do with Persistent=true, which runs the job as soon as the machine comes back. If a missed run matters — a backup, an invoice batch — do not use plain cron on a machine that is not always on.

Stopping two runs from overlapping

Cron will happily start a second copy while the first is still going, and that is how a five-minute job on a five-minute schedule turns into forty copies competing for the same database. On Linux, wrap the command in flock -n /tmp/myjob.lock, which simply does nothing if the lock is held. On Kubernetes set concurrencyPolicy: Forbid on the CronJob. In any language, a lock file or an advisory database lock at the top of the job does the same thing. The overlap check above compares how long you say the job takes against the shortest gap in the schedule.

What % means in a crontab

It is the single most surprising character in the file. In a command, an unescaped % is turned into a newline, and everything after the first one is fed to the job on standard input. That is why date +%Y-%m-%d in a crontab is cut off at the first %: date only receives +, and the rest goes to its standard input. Escape every one of them as \%, or put the command in a script file where % behaves normally — which is the better habit anyway.

Testing a cron expression without waiting

Read the next run times above: they are computed with the same day-matching rules the scheduler uses, in the zone you select, with daylight-saving transitions applied. For the command itself, run it the way cron will: env -i /bin/sh -c 'your command here'. On systemd, systemd-analyze calendar 'Mon..Fri 09:00' prints the next elapse. On Kubernetes, kubectl create job --from=cronjob/myjob manual-run-1 runs it immediately without touching the schedule.

How accurate the run times are

The run times are computed in your browser with the same day-matching rules the scheduler uses — including the day-of-month / day-of-week OR rule, steps that do not divide evenly, leap years and month ends — in the timezone you pick, with daylight-saving transitions applied.

What the page cannot know is whether your server is up, whether the previous run is still going, or whether the machine’s clock is right. It tells you when the schedule fires, not whether the job succeeds.

Sharing an expression

The link button copies a URL carrying the expression, the platform and the timezone, so whoever opens it sees exactly what you saw rather than their own defaults. The address bar updates as you type, so a plain bookmark works too.

Privacy

Nothing you type is sent anywhere. The parser, the schedule calculation and the timezone conversions all run in the page, on your device. There is no API call and no logging of what you type; the only analytics on the site are privacy-first page counts. You can open the network tab and watch nothing happen, or disconnect entirely — the page keeps working.

Related tools