What Is M Codes in CNC Machine Control
M codes in a CNC machine handle everything the cutter does not do: spindle on and off, coolant, tool change, pallet position, program stop and end. This page explains what each group actually switches, how M codes differ from G codes, and where controllers stop agreeing. Written for engineers and buyers who read a program and want to know why a machine behaved the way it did.

In this article
- 1
- 2
- 3
- 4
- 5
- 6
- 7
M Codes in CNC Machine: What the Letter Actually Switches
An M code is a miscellaneous function. The controller reads it and operates something other than axis motion. Spindle rotation, coolant valves, the automatic tool changer, pallet shuttle, chuck clamp, program stop and program end all sit behind M addresses. G codes move the tool along a path. M codes decide whether that path is cut wet or dry, in which spindle direction, and whether the machine keeps going after the block finishes.
The block format is simple. A line like N120 M08 carries a sequence number and the M word, and nothing else is required. Some controllers accept M codes on the same line as a motion command, some do not. Fanuc typically allows M03 and M08 in a G01 block, while certain older controls require a separate line. If a machine ignores a coolant command, check this first before blaming the pump.
M codes are modal in a loose sense, but not uniformly. M03 stays active until M05 cancels it. M08 stays on until M09. M06 executes once and finishes. M30 ends the program and rewinds. That mix of latching and one-shot behavior is the part that trips up new programmers, because the same letter covers both state and event.
- 1State codesM03, M04, M08 stay active until canceled.
- 2Event codesM06, M00, M01 fire once and complete.
- 3Program codesM30 ends and rewinds the program.
The M Codes You See in Almost Every Program
M00 is a program stop. The machine halts, the spindle stops, and an operator must press cycle start to continue. It is used for manual checks, flipping a part, or clearing chips. M01 is an optional stop, and it only takes effect when the optional stop switch on the panel is on. Shops use M01 for first-article runs so the operator can measure between operations without editing the program.
M03 starts the spindle clockwise, M04 counterclockwise, M05 stops it. Spindle speed comes from an S word, usually on the same line or the line before. M06 calls the next tool. On a machine with a carousel or umbrella changer, the T word selects the pocket and M06 executes the swap. On some controls the tool is pre-staged while cutting, which shortens the change to a few seconds.
M08 turns coolant on, M09 turns it off. Flood, mist and through-spindle variants use different numbers on many machines, so M08 may mean flood on one controller and mist on another. M30 ends the program, stops the spindle, turns off coolant and returns the cursor to the top. It is the cleanest way to finish a main program.
- 1Watch the S wordM03 without S runs at the last programmed speed.
- 2Coolant type variesM07, M08 and M51 mean different things across brands.
Where M Codes Stop Being Portable
The M code list is not a global standard below the first dozen entries. M00 through M09 are close to universal. Past M30, each builder assigns numbers to its own hardware. A pallet change, a bar feeder, a tailstock quill, a chip conveyor, a probe cycle and a rotary table clamp all get numbers from the upper range, and those numbers are machine-specific.
M19 orients the spindle to a fixed angle so a tool can enter a specific pocket or engage a manual tool change. Fanuc and Haas both use M19, but the orientation angle and the way it is set differ. Some machines accept an R or P value on the M19 line, others read a parameter. If spindle orientation is wrong, the problem is usually a parameter, not the program.
Subprogram calls follow the same pattern. M98 calls a subprogram and M99 returns, but Haas uses M97 for a local sub, and some controls use M98 with an L repeat count while others use a P address. When a program is moved between a Fanuc mill and a Haas mill, these are the lines that break.
- 1Read the manualUpper-range M codes are builder-defined.
- 2Test on airRun unknown M codes with the spindle stopped first.
Why M Code Choice Changes Part Quality
Coolant timing affects dimensions. Turning M08 on one block before the tool enters the cut lets the pump reach pressure and the nozzle line fill. Starting the cut dry for even half a second raises edge temperature on titanium and 17-4PH, which shows up later as tool wear and a drifting bore size. On aluminum, dry entry mostly costs surface finish.
Spindle direction matters on tapping and on left-hand tools. M03 with a right-hand tap and a reversing spindle is the correct cycle on most controls, but rigid tapping uses a dedicated G84 cycle with its own retract. Mixing M04 into a standard tap block will strip the thread or break the tap.
Tool change position is another quality lever. If M06 runs at a Z height that is too close to the fixture, the changer arm can clip a clamp. The safe practice is a G91 G28 Z0 or a fixed G30 second reference point before every M06. On our 5-axis centers, the second reference point is set per fixture so the trunnion swings clear.
- 1Coolant lead timeOne block early prevents dry entry.
- 2Safe Z before M06Use G28 or G30, never rely on the last cut depth.
How Fanuc, Haas and Siemens Differ
Fanuc keeps the core M codes stable across its series, which is why so much training material is written around it. The differences appear in the upper range and in parameter-driven behavior. M19 orientation angle, M code for a pallet change, and the way a subprogram is called all depend on the model and the option package installed.
Haas uses the same low-number set but adds shortcuts. M97 calls a local subprogram inside the same file, while M98 calls an external one. M06 tool change logic on a Haas mill with a side-mount changer pre-stages the next tool, so the visible pause is much shorter than on an umbrella changer. The program looks identical, the cycle time does not.
Siemens controls on turning centers often follow a different convention, where some auxiliary functions are handled by M commands that map to PLC outputs rather than to fixed functions. On those machines, M08 might be wired to a specific solenoid by the integrator. A program moved from a Fanuc lathe to a Siemens lathe can run without alarm and still do the wrong thing.
- 1Low numbers travelM00 to M09 are close to portable.
- 2High numbers do notVerify each one against the builder manual.
How We Validate M Code Behavior Before a Production Run
This is the sequence we use on new programs, especially when the same file will run on more than one machine model.
- 1List every M code in the filePull the program into an editor and extract unique M words. Compare the list against the controller manual for that specific machine, not a generic chart.
- 2Run dry with the spindle disabledUse single block and a feed override at zero. Watch which codes latch and which fire once. Confirm M08 opens the correct coolant line.
- 3Check safe Z before every M06Confirm the machine returns to G28 or G30 before the changer moves. Set the second reference point per fixture on 5-axis work.
- 4Verify spindle orientation for boringCommand M19, then measure the orientation angle with a dial indicator on a test bar. Adjust the parameter if it is off.
- 5Air-cut the first partRun the full program with no stock at 25 percent rapid and 50 percent feed. Confirm M01 stops land where the operator needs them.
- 6Cut one part and inspectMeasure the first article against the drawing. If a dimension drifts during the run, revisit coolant timing and spindle warm-up, not the geometry.
M Code Groups and What They Control
Numbers below M30 are widely shared. Upper-range numbers are builder-specific and must be checked against the machine manual.
| Code | Function | Behavior | Typical use |
|---|---|---|---|
| M00 | Program stop | Halts, needs cycle start | Manual check, chip clear |
| M01 | Optional stop | Active only if switch is on | First-article inspection |
| M03 / M04 | Spindle CW / CCW | Stays on until M05 | Milling, tapping |
| M05 | Spindle stop | Cancels M03 or M04 | End of cut sequence |
| M06 | Tool change | One-shot event | Next tool in program |
| M08 / M09 | Coolant on / off | Stays on until M09 | Flood or mist cooling |
| M19 | Spindle orientation | One-shot, angle set by parameter | Tool change, boring bar entry |
| M30 | Program end | Stops spindle, rewinds | End of main program |
The Practical Rule
If a program will only ever run on one machine, use that builder's M codes freely and document them. If the same file must run on a Fanuc, a Haas and a Siemens, keep everything above M09 in a separate setup section and rewrite it per machine. Portable programs stop at M09 for a reason.
M Code Questions Engineers Ask
What is the difference between M codes and G codes?
G codes command motion: rapid, feed, arc, drilling cycle, coordinate system. M codes command everything else: spindle, coolant, tool change, program flow.
A single block often carries both. G01 X50.0 F200 M08 moves the tool and turns coolant on at the same time.
Does M03 always need an S word?
No, but if you omit S the spindle runs at whatever speed was last programmed. That is a common cause of a broken tool after a manual edit.
Put the S word on the same line as M03 or the line before it, and check it in single block.
Why does M08 not turn on coolant on my machine?
On many machines M08 is flood, M07 is mist, and through-spindle coolant uses a higher number set by the builder. The pump may also need a manual valve open or a pressure interlock satisfied.
Check the electrical ladder or the manual before editing the program.
Can M codes run on the same line as a motion command?
Usually yes for M03, M04, M05, M08 and M09. M06 is often safer on its own line because the tool change needs the machine at a known position.
Older controls reject mixed blocks. If a line is ignored, split it.
What happens if M30 is missing at the end of a program?
The controller may sit at the last block with the spindle stopped but coolant still on, and the cursor will not rewind. The next cycle start can behave unexpectedly.
End every main program with M30 and confirm the coolant and spindle are off.
Are M codes the same on a lathe and a mill?
The low numbers are close, but lathes add chuck clamp, tailstock, bar feeder and parts catcher codes in the upper range. Those are builder-specific.
Do not move a lathe program to a mill or the reverse without rewriting the auxiliary section.
Send Us the Drawing, Not Just the CAD File
Our engineering team reviews the print, the material and the tolerance stack before quoting. Quotation and a free DFM analysis come back within 12 hours, and production can start within 24 hours of approval.
12-hour quoteDFM feedback100% inspection