The basic method
Run time, at its simplest, is distance ÷ speed, done for every move and added up. Sort each move into one of three buckets:
Feed moves (G1, G2, G3): length ÷ the programmed feed rate.
Rapid moves (G0): length ÷ the machine’s rapid rate, not the feed.
Fixed time: dwells (G4), tool changes, and the like. Add them as-is.
Sum all three and you have an estimate. Let’s walk one through.
A worked example
Here’s a short program. Plunge in, cut a 60 × 40 mm rectangle, retract:
G21 G90 ; mm, absolute (tool starts at origin: X0 Y0 Z0)
G1 Z-3 F200 ; plunge 3 mm (Z0 to Z-3)
G1 X60 Y0 F1000 ; cut 60 mm
G1 X60 Y40 ; cut 40 mm
G1 X0 Y40 ; cut 60 mm
G1 X0 Y0 ; cut 40 mm
G0 Z2 ; rapid retract
M30
One thing to settle first: the program never sets a starting Z, so the tool begins at the origin, Z0. The plunge is therefore 3 mm (down to Z-3), and a comment like ( tool at Z2 ) wouldn’t change that. Comments don’t move the tool, only real moves do. Take the machine’s rapids as 5000 mm/min in XY and 2000 mm/min in Z (the viewer’s defaults). The retract is a Z move, so it uses the slower Z rapid. Now go line by line, distance ÷ speed for each move:
| Move | Distance | Speed | Time |
|---|---|---|---|
| G1 Z-3 (plunge) | 3 mm | 200 mm/min | 0.90 s |
| G1 X60 Y0 | 60 mm | 1000 mm/min | 3.60 s |
| G1 X60 Y40 | 40 mm | 1000 mm/min | 2.40 s |
| G1 X0 Y40 | 60 mm | 1000 mm/min | 3.60 s |
| G1 X0 Y0 | 40 mm | 1000 mm/min | 2.40 s |
| G0 Z2 (retract) | 5 mm | 2000 mm/min (Z rapid) | 0.15 s |
| Total | — | — | ≈ 13.1 s |
So the back-of-the-envelope answer is about 13.1 seconds. For a quick sanity check (“is this a two-minute job or a two-hour job?”) that’s often all you need.
Where the hand method breaks down
Now run the same snippet in the viewer and it reports 0:13, which looks shorter than 13.1 s, but isn’t. Two things are going on. The viewer rounds to whole seconds, so anything from 12.5 to 13.5 s shows as 0:13. And our 13.1 s assumes the tool jumps straight to full speed and rounds every corner without slowing, which it doesn’t. Every move ramps up and back down, and the tool nearly stops at each sharp corner, then re-accelerates (the physics is in feed rate vs. cycle time). So the real run sits a little above 13.1 s, never below it. The simulator and our hand figure agree to within a few tenths, both landing on 0:13. 13.1 s is a floor. A motion accurate run can only be equal to or longer.
To see how much overhead this adds, correct one move. Take the 60 mm cut at F1000 (16.67 mm/s) on the viewer’s default 250 mm/s² acceleration. It needs only about 0.56 mm to ramp up and the same to ramp down, so it does reach feed, but those ramps add roughly 2 × v/a ≈ 0.13 s on top of the naive 3.60 s. On a long move that’s nothing. The real cost is the corners: this little rectangle has four of them, and at each one the tool sheds nearly all its speed and rebuilds it. Add the plunge, and the genuine run sits a few tenths above the 13.1 s floor, still 0:13 at the viewer’s whole second resolution.
On this simple part the gap is small. On a part with hundreds of short segments and tight detail, those per-move ramps and per-corner near stops stack into real minutes, and the hand estimate can be badly low. The size of the gap depends entirely on the geometry and your machine’s acceleration, which is why there’s no single multiplier that fixes it.
Why you simulate instead
To get the true number by hand you’d have to compute a full acceleration profile for every block, apply the corner speed limit v = √(a·R) at every vertex, and check that no move demands more acceleration than the machine has, then sum it all. For a real program of thousands of lines that’s impractical and error-prone. A motion accurate simulator does exactly that calculation, every block, in milliseconds.
Do it instantly
Paste the snippet above, or your own file, into UltraNC, set your machine’s rapid and acceleration limits, and read the estimated run time. It includes the acceleration and cornering the hand method skips, so you get the real figure rather than the floor. Nothing is uploaded, and there’s no sign up.
Common questions
How do you calculate CNC run time from G-code?
Sum each move's length divided by its speed, with feed moves (G1/G2/G3) at the programmed feed and rapids (G0) at the machine's rapid rate. Then add fixed times like dwells and tool changes. It gives a quick estimate, but treat it as a floor: the real run is longer once acceleration and cornering are accounted for.
Why is my hand-calculated run time too low?
The distance-over-feed method assumes the tool instantly reaches the programmed feed and never slows for corners. Real machines accelerate and decelerate, and nearly stop at sharp corners, so actual run time is longer, and much longer on programs full of short moves and detail.
Do rapid moves count toward run time?
Yes. G0 rapids run at the machine's rapid rate rather than the programmed feed, and on programs with a lot of repositioning they can be a large share of the total. Always include them, at the rapid rate, not the feed.
Part of the guide: How to estimate CNC machining time from G-code
Related: Feed rate vs. cycle time: why the hand method runs low.