
Blog
How to Calculate Filament Usage from G-code: Per-Layer Extrusion Parsing
April 22, 2026
How to walk a G-code file and compute millimeters of filament extruded per slot per layer — the technique behind accurate cost accounting when a print fails or is cancelled partway through.
G-code is a stream of plain text. Every move a printer makes — every millimeter of filament pushed through the nozzle — is recorded in it. This means you can calculate, with millimeter precision, exactly how much filament each slot consumed up to any layer in the file.
Printago does this to answer a question that sounds simple but isn't: when a print fails at layer 47 of 200, how much filament did it actually use? The slicer's header reports total usage for the full job. It tells you nothing about partial completion. To get that, you have to walk the G-code yourself.
Why the Slicer's Header Isn't Enough
Every G-code file contains metadata in its header and footer — lines like:
; filament used [mm] = 4823.21, 1432.18
; filament used [g] = 14.21, 4.25These are accurate for a completed print. For a cancelled or failed print, they're useless — they describe the full job, not what actually ran.
To track partial usage, you need to know how much was extruded up to the layer where the print stopped. That requires walking the file and accumulating extrusion per layer, per filament slot.
How G-code Tracks Extrusion
Every move command (G0, G1, G2, G3) can include an E parameter — the extruder axis position. The delta in E between two moves is how much filament was fed:
G1 X100 Y50 E10.234 F3600 ; move to X100,Y50 while extruding to E=10.234
G1 X150 Y50 E11.891 F3600 ; continue — delta is 11.891 - 10.234 = 1.657mm extrudedThere are two extrusion modes:
- Absolute (
M82, the default):Eis a running total. Delta = currentEminus previousE. - Relative (
M83):Eis the amount to extrude for this move directly.
G92 E0 resets the reference point without moving — it's a checkpoint that sets "current E = 0" so deltas are computed from here. Miss one of these and every subsequent delta is wrong.
Tracking Tool Changes
Multi-color G-code switches slots with Tn commands:
T0 ; activate slot 0
; ... extrusion on slot 0 ...
T1 ; switch to slot 1
; ... extrusion on slot 1 ...Bambu firmware also emits T-codes with values well outside the normal slot range for internal operations (nozzle maintenance, system events, unload sequences). Treat anything outside your configured slot count as a non-material command and don't update currentSlot for it — otherwise subsequent extrusion gets attributed to a nonexistent slot.
Layer Detection
Different slicers mark layer transitions differently:
| Slicer | Layer comment |
|---|---|
| Orca Slicer / Bambu Studio | ; CHANGE_LAYER or ; LAYER_CHANGE |
| PrusaSlicer / SuperSlicer | ; LAYER_CHANGE |
| Cura | ;LAYER:N |
| Generic | ; LAYER:N or ; layer N |
When a layer comment is encountered, the current layer index increments. Extrusion before the first layer comment (startup sequences, priming moves) goes into layer 0.
Flush Sections
Bambu and Orca Slicer insert purge sequences between tool changes, wrapped in ; FLUSH_START / ; FLUSH_END markers. Whether to attribute that extrusion to the outgoing slot, to a "purge" bucket, or to drop it entirely depends on what you're measuring — cost accounting, part geometry analysis, and filament inventory all want different answers. It's worth detecting these sections explicitly so you can route them however your use case needs.
Computing Partial Usage
Once you have per-layer extrusion data, partial usage is straightforward:
function usageAtLayer(
analysis: ExtrusionAnalysis,
stoppedAtLayer: number
): Record<number, number> {
const usedMmBySlot: Record<number, number> = {};
for (const layer of analysis.layers) {
if (layer.layer > stoppedAtLayer) break;
for (const [slot, mm] of Object.entries(layer.slots)) {
usedMmBySlot[Number(slot)] = (usedMmBySlot[Number(slot)] ?? 0) + mm;
}
}
return usedMmBySlot;
}Convert to grams using the gramsPerMmBySlot ratio derived from the slicer header:
// gramsPerMm = reported_grams / reported_mm, computed per slot
const usedGramsBySlot: Record<number, number> = {};
for (const [slot, mm] of Object.entries(usedMmBySlot)) {
const ratio = analysis.gramsPerMmBySlot?.[Number(slot)];
if (ratio) {
usedGramsBySlot[Number(slot)] = mm * ratio;
}
}This gives you per-slot gram consumption for any stopped layer — accurate enough for cost accounting and material inventory tracking.
Cross-Checking Against Slicer Reports
The slicer embeds total reported usage in its header/footer. For a completed print, your computed total should match:
// Computed totals from walking the G-code
analysis.totalBySlot // { 0: 4821.3, 1: 1430.9 }
// Slicer-reported totals from header comments
analysis.reportedTotalBySlot // { 0: 4823.21, 1: 1432.18 }A few mm of variance is normal — rounding in the header comments, slightly different handling of retraction moves. A variance of more than 1% suggests a parsing bug (wrong extrusion mode, missed G92, or misidentified layer boundaries).
What This Enables
Per-layer extrusion data unlocks use cases that slicer metadata alone can't support:
- Partial print cost accounting: charge for filament actually consumed, not the full job estimate
- Filament inventory deduction on cancellation: deduct actual usage, not projected usage
- Failure analysis: see which layer a print stopped at and how much material was wasted
- Multi-slot usage breakdown: for multi-color prints, know exactly how much each slot contributed
Printago uses this to maintain accurate filament inventory — when a job fails at layer 50, the AMS slot balances are decremented by the actual grams consumed through that layer, not the full job amount.
Slicer Compatibility
The parser handles G-code from all major slicers, because the underlying extrusion mechanics are standard G-code:
| Slicer | Layer comments | Flush sections | Tested |
|---|---|---|---|
| Orca Slicer | ; CHANGE_LAYER |
; FLUSH_START/END |
Yes |
| Bambu Studio | ; CHANGE_LAYER |
; FLUSH_START/END |
Yes |
| PrusaSlicer | ; LAYER_CHANGE |
None | Yes |
| SuperSlicer | ; LAYER_CHANGE |
None | Yes |
| Cura | ;LAYER:N |
None | Yes |
| Simplify3D | ; layer N |
None | Partial |
The main differences are in layer comment format and the presence of flush sections. The E-axis mechanics — absolute/relative mode, G92 resets, G0/G1 moves — are identical across all of them.
Sign up for free today
No credit card required. Connect unlimited printers and get production automation running in minutes.