Cron Expression Builder

Build a cron expression from plain settings, read an existing one in English, and see exactly when it will next run.

Free · no signup · works offline · checked 2026-08-04

Presets

Next 5 runs (server time, assumed UTC)

Illustration representing Utilities.

The five fields

*  *  *  *  *
│  │  │  │  └── day of week   (0-7, 0 and 7 both mean Sunday)
│  │  │  └───── month         (1-12)
│  │  └──────── day of month  (1-31)
│  └─────────── hour          (0-23)
└────────────── minute        (0-59)

Operators: * every value, , a list, - a range, / a step. So */15 in the minute field means every fifteen minutes, and 1-5 in day-of-week means Monday to Friday.

The trap that catches everyone

When you set both day-of-month and day-of-week, cron runs the job if either matches — not both.

0 0 13 * 5    # midnight on the 13th, AND every Friday. Not just Friday 13th.

That’s the documented behaviour, it surprises nearly everyone, and it’s why a job you meant to run monthly ends up running weekly. If you need both conditions, match on one in cron and check the other in your script.

Which timezone it uses

The server’s, not yours. A job set for 0 9 * * * runs at 9am wherever the server thinks it is, which on most hosting is UTC. Check with date over SSH, or date_default_timezone_get() in PHP, before assuming.

Daylight saving makes this worse: jobs scheduled in the skipped hour don’t run, and jobs in the repeated hour run twice. Schedule anything important outside 01:00–03:00 local time.

On free hosting there is no cron

Free plans almost never include scheduled tasks — running them across hundreds of thousands of mostly dormant accounts is expensive. Two workarounds:

An external trigger. Free services like cron-job.org fetch a URL on a schedule. Put your task behind a secret URL and let them call it. Check the secret in your script, or you’ve built a public endpoint anyone can hammer.

WordPress’s built-in cron, which isn’t real cron. wp-cron.php runs on page load, so a scheduled task fires inside a visitor’s request and consumes one of your limited PHP process slots — a frequent cause of 508 errors. Disable it with define('DISABLE_WP_CRON', true); and trigger it externally instead.