G-code Explainer & Simulator
Paste a CNC program and read every line in plain English, see the toolpath plotted, and get the cut length, rapid length and an estimated run time. Mill and lathe, LinuxCNC and Haas-style codes. Unknown codes are flagged, never guessed.
How to Use
- Pick a preset (Square profile, Circle with G02 arcs, Drilling cycles, Lathe face and turn or Spot the mistakes) or paste your own program into the box and press Simulate (or Ctrl+Enter).
- Choose Mill or Lathe and the dialect: LinuxCNC (NGC), which follows the RS-274/NGC rules, or Haas (Fanuc-style). The dialect settles the codes that differ between machines, such as G04 P10 (10 s or 10 ms), lathe X as a diameter, and G98/G99 on a lathe.
- Read the plot: rapids are dashed, feed moves solid, arcs are drawn as true arcs. Step with ◀ and ▶, drag the slider or click a row of the table; the current line turns orange and the dot shows where the tool is after it.
- Check the readouts and the checks list: cut distance, rapid distance, estimated run time (set your machine’s rapid rate; the default is 5,000 mm/min), extents and tools, then any errors or warnings with a button that jumps to the line.
- Open Show Work below the tool for every block’s modal state (G01 G17 G21 G90 G94 G54 …), its start and end position, distance and time.
- Need the whole list of codes? The G-code and M-code reference has every common G and M code in one table. The address keeps
?preset=and?units=, so a link reopens the same run.
Looking for a G-code list? G-code & M-code reference: every common code in one table → Or paste a program below to have each line explained.
Worked Example
A nine-line mill program, checked by hand (LinuxCNC rules, rapids at 5,000 mm/min):
G21 G17 G90 G94 M03 S1000 G00 X0 Y0 Z5 G01 Z-1 F100 X30 F300 G03 X40 Y10 I0 J10 G00 Z5 M05 M30
Line 1 sets millimetres, the XY plane, absolute positions and feed per minute; line 2 starts the spindle at 1,000 rpm. Line 3 rapids to X0 Y0 Z5, but nobody knows where the tool was before it, so this first move is plotted as a start point and not counted.
Line 4 feeds Z from 5 to −1: 6 mm at 100 mm/min = 6 ÷ 100 min = 3.6 s.
Line 5 (G01 still active) feeds X from 0 to 30: 30 mm at 300 mm/min = 6 s.
Line 6 is an anticlockwise arc. I0 J10 puts the centre 10 mm above the start, at X30 Y10, so the radius is 10 mm. The start (X30 Y0) is straight below the centre and the end (X40 Y10) is to its right: a quarter turn, 90°. Arc length = 2π × 10 × 90/360 = 15.708 mm, at 300 mm/min = 3.142 s.
Line 7 rapids Z from −1 to 5: 6 mm at 5,000 mm/min = 0.072 s. Lines 8 and 9 stop the spindle and end the program.
Totals: cut distance 6 + 30 + 15.708 = 51.708 mm, rapid distance 6 mm, estimated time 3.6 + 6 + 3.142 + 0.072 = 12.81 s. Run this example.
The common mistake: an arc end point that is not on the circle. Type G03 X40 Y12 I0 J10 instead. The centre is still X30 Y10 (I and J are measured from the start), so the start is 10 mm from the centre but the end is √(10² + 2²) = √104 = 10.198 mm away. The two radii differ by 0.198 mm. LinuxCNC refuses an arc whose radii differ by more than 0.005 mm and 0.1% of the radius (here 0.010 mm), or by more than 0.5 mm, with the error “Radius to end of arc differs from radius to start”; the NIST RS274/NGC interpreter of 2000 allowed only 0.002 mm. This tool flags the line as an error and still draws the spiral the numbers describe, so you can see how far off it is. Run the mistake.
Same rapid, two time estimates. G00 from X0 Y0 to X30 Y10 is a straight line of √(30² + 10²) = 31.623 mm. LinuxCNC moves the axes together along that line, so at 5,000 mm/min it takes 31.623 ÷ 5,000 min = 0.379 s. Haas describes its rapids as each axis moving at full speed, so the time is set by the longer axis: 30 ÷ 5,000 min = 0.360 s, and the path is a dog-leg, not a straight line. The Dialect option switches between the two, and the plot always shows the straight line between the end points.
Show Work
How It Works
How a program is read. Each line is split into words (a letter and a number), with comments in ( ) or after ; set aside. Codes on one line run in the order LinuxCNC documents, not the order they are written: feed mode, F, S, T, M06, spindle, coolant, dwell, plane, units, cutter compensation, tool length, work offset, distance mode, return mode, G28/G92, then the move, then M00/M02/M30. Modal codes stay in force until another code from the same group replaces them, which is why a bare X40. line still feeds at the last F.
What is not guessed. A code that is not in this tool’s list is flagged and skipped, never interpreted. Macros (#1, [2+3]), O-word loops and subprogram calls are not run. Positions the tool cannot know are shown as “?”: the start of the program, after G28 or G53 (machine coordinates), after a change of work offset, or after a cycle it does not simulate (G70–G72 and G76 on lathes, Haas G90/G94 lathe cycles, probing). Moves from or to such a point are not counted. Cutter compensation (G41/G42) and tool length offsets (G43) are explained but the plot shows the programmed path, not the offset one. The time leaves out acceleration, tool changes, spindle start-up and operator stops, so a real machine takes longer.
Lathes. The side view puts Z across and X up from the centreline, with the other half of the part shown faintly below it, so G02 is drawn clockwise as seen from the front of the screen. LinuxCNC’s lathe notes point out that on a typical lathe, where +Y points at the floor, G02 and G03 only look like their names when seen from below, so from above they appear reversed. X words are diameters in the Haas dialect (its G71 page gives the X finish allowance U as a diameter) and distances from the centreline in LinuxCNC unless G7 is active. Arc I offsets are distances from the start to the centre, so they stay radii; LinuxCNC says so explicitly for G7.
Sources: LinuxCNC documentation, G-Codes, M-Codes, G-code Overview (modal groups, order of execution, comments) and Lathe User Information; T. R. Kramer, F. M. Proctor and E. Messina, The NIST RS274NGC Interpreter, Version 3, NISTIR 6556, 2000; Haas Automation’s mill and lathe G-code and M-code pages (G00, G01, G02/G03, G04, G17, G20, G28, G40–G43, G54, G73, G80, G81, G83, G90, G94, G98; lathe G00–G02, G28, G50, G71, G90, G94, G96–G99; M02, M03–M06, M08/M09, M30); the Grbl v1.1 README for its supported-code list.
Where G-code Comes From
RS274. G-code is the everyday name for RS274, a programming language for numerically controlled machine tools. NIST’s interpreter report describes the most recent standard version, RS274-D, as completed in 1979 and published by the Electronic Industries Association as EIA-274-D, and adds a warning that still holds: implementations differ from machine to machine, so a program that runs on one maker’s machine probably will not run on another’s. That is why this tool has a dialect switch.
RS274/NGC. The Next Generation Controller (NGC) project wrote a fuller specification. Allen-Bradley prepared the first draft, “RS274/NGC for the LOW END CONTROLLER”, dated 24 August 1992; the National Center for Manufacturing Sciences released a second draft in August 1994. At the National Institute of Standards and Technology, the Enhanced Machine Controller (EMC) project built an interpreter for the language: version 1 was described in April 1994, and version 3, the report this tool cites, by Thomas Kramer, Frederick Proctor and Elena Messina, is dated 17 August 2000. Its RS274/VGER variant was written to read Fanuc-flavoured code for a retrofitted 5-axis machine.
Today. LinuxCNC’s documentation states that its G-code language is based on RS274/NGC, and its modal groups and order of execution are the ones used here. Industrial controls such as Haas’s keep the same core (G00–G03, G17–G21, G40–G43, G54–G59, G81, G83, M03–M06, M08/M09, M30) but differ in the details this tool flags, such as dwell units, rapid paths and the lathe codes. Small controllers support less: Grbl v1.1 lists G0–G3, G38.2–G38.5 and G80 as its motion modes, with no drilling cycles, no G41/G42 cutter compensation and no M6 tool change.
About This Tool
Reference: Surface Finish (Ra) Chart.
Reference: Speeds & Feeds Chart.
Reference: M-Code Reference by Controller.
Reference: Canned Cycles Reference.
This tool reads a CNC program the way a controller does, one block at a time with its modal state, and turns it into three things: a plain-English explanation of every word on every line, a plot of the toolpath with rapids, feeds and true arcs in a top and a front view (or a side view for lathes), and totals for cut distance, rapid distance, extents, tools and an estimated run time. Six checks run on every program: feed moves with no F, arcs whose end point is off the circle, units, plane and distance mode not set before the first move, cutting with the spindle off, cutter compensation left on, and a missing M30 or M02.
What it adds to a plain G-code viewer: each code’s meaning is taken from published documentation (LinuxCNC, the NIST RS274/NGC report and Haas’s code pages), the places where machines disagree are named rather than silently picked, and anything it does not know is flagged instead of guessed. Everything runs in your browser; the program you paste is not uploaded. For the code meanings alone, see the G-code and M-code reference.
It is for machinists and CNC students reading a program before running it, hobbyists checking a CAM post for a LinuxCNC or Grbl machine, and programmers learning how a modal language works. It is not a substitute for the machine’s own graphics and a dry run.
Related tools: Execution Visualizer, Circle Calculator, and Unit Converter.
Frequently Asked Questions
What are the most common G-codes and M-codes?
Motion: G00 rapid, G01 straight feed, G02 clockwise arc, G03 anticlockwise arc, G04 dwell. Set-up: G17/G18/G19 plane, G20 inch, G21 mm, G90 absolute, G91 incremental, G54–G59 work offsets, G40/G41/G42 cutter compensation, G43/G49 tool length offset, G28 return home. Drilling: G81 drill, G83 peck drill, G80 cancel. M-codes: M03/M04/M05 spindle clockwise, anticlockwise, stop; M06 tool change; M08 flood coolant, M09 off; M30 (or M02) program end. Paste a program here and each line is explained; the full table is in the G-code and M-code reference.
What is the difference between G00 and G01?
G00 moves at the machine’s rapid rate and is for positioning, never cutting. G01 moves in a straight line at the programmed feed rate F and is for cutting; LinuxCNC refuses a G01 before any F has been set. In the Square profile preset the 166.5 mm of G01 moves take 17.95 s at F200 and F600, while the 6.5 mm rapid takes 0.08 s at 5,000 mm/min. LinuxCNC moves all axes of a G00 together in a straight line; Haas says its rapids are generally not a straight line because each axis runs at full speed, so the path can dog-leg.
How do G02 and G03 arcs work with I, J, K and R?
The X/Y/Z words give the end point. I, J and K give the centre as an offset from the start point (I along X, J along Y, K along Z; G17 uses I and J). From X30 Y0, G03 X40 Y10 I0 J10 has its centre at X30 Y10, a radius of 10 mm and turns 90° anticlockwise: π × 10 ÷ 2 = 15.708 mm of cutting. With R instead, a positive R means 180° or less and a negative R more than 180°, and a full circle needs I/J/K. If the end point is not on the circle, LinuxCNC stops when the two radii differ by more than 0.005 mm and 0.1% of the radius (or 0.5 mm): ending at Y12 instead of Y10 misses by 0.198 mm.
What does G28 do, and why is it written G91 G28 Z0?
G28 sends axes home by way of an intermediate point given by the axis words. Haas’s home is machine zero; LinuxCNC’s is the position stored with G28.1 (the machine origin if none is stored). In absolute mode, G28 Z0 first moves to Z0 of the part, which is down onto the work. In G91 the Z0 is a distance of zero, so Z goes straight home; Haas’s own example shows G28 G91 X0 Y0 Z0 moving directly to machine zero. This tool marks the position after G28 as unknown, because it depends on the machine.
Why do lathe programs write X as a diameter, and what do G98 and G99 mean on a lathe?
Haas lathes program X as a diameter, with U and W as incremental X and Z, and use G98 for feed per minute and G99 for feed per revolution; their G90 and G94 are turning and facing cycles, not absolute mode and feed per minute. LinuxCNC starts lathes in radius mode (G8), switches to diameters with G7, uses G95 for feed per revolution and keeps G98/G99 for canned-cycle retracts. In the Lathe preset, G96 S150 at a 52 mm diameter is 150,000 ÷ (π × 52) = 918 rpm, so F0.2 mm/rev feeds at 183.6 mm/min.
How do I use the G-code Explainer & Simulator?
Simply type your numbers and read the result, which refreshes the instant you change something. There is nothing to submit and nothing to wait for.
Do I need to install or sign up for anything?
Not at all — it runs in the browser with nothing to install and no account. After it loads once, it even works without an internet connection.
Is my information private?
Yes. Everything happens in your browser. Nothing you type is sent to a server or saved anywhere.
Common Use Cases
Check a program before it runs
Paste a CAM post or a hand-written program: a G03 that ends 0.198 mm off its circle is flagged as an error (LinuxCNC’s limit is 0.005 mm), as is a G01 with no F.
Learn G-code line by line
The Square profile preset explains all 19 blocks, from G21 G17 G40 G49 G80 G90 G94 to M30, and plots the 40 × 40 mm square it cuts.
Estimate a cycle time
The Drilling cycles preset drills 4 holes: 49.52 mm of feed and 289.48 mm of rapids, about 28.2 s with rapids at 5,000 mm/min. Enter your machine’s rapid rate for a closer figure.
Move a program between machines
Switch the dialect to see what changes: G04 P10 is a 10 s dwell on LinuxCNC but 10 ms on a Haas, and G90 on a Haas lathe is a turning cycle.
Teach the classic mistakes
The Spot the mistakes preset hides six: no units, a G01 with no F, the spindle never started, an arc end point 0.198 mm off, G41 never cancelled and no M30. The checks list catches all six.
Last updated: