diff --git a/Marlin/Configuration.h b/Marlin/Configuration.h
index af98be4d1badb4cb234c5dd3afa1217e2174748d..fccdf9ced3aaecdabe0bda6e5e0ce01ecd339454 100644
--- a/Marlin/Configuration.h
+++ b/Marlin/Configuration.h
@@ -1595,6 +1595,10 @@
 
   // Enable for a purge/clean station that's always at the gantry height (thus no Z move)
   //#define NOZZLE_CLEAN_NO_Z
+
+  // Explicit wipe G-code script applies to a G12 with no arguments.
+  //#define WIPE_SEQUENCE_COMMANDS "G1 X-17 Y25 Z10 F4000\nG1 Z1\nM114\nG1 X-17 Y25\nG1 X-17 Y95\nG1 X-17 Y25\nG1 X-17 Y95\nG1 X-17 Y25\nG1 X-17 Y95\nG1 X-17 Y25\nG1 X-17 Y95\nG1 X-17 Y25\nG1 X-17 Y95\nG1 X-17 Y25\nG1 X-17 Y95\nG1 Z15\nM400\nG0 X-10.0 Y-9.0"
+
 #endif
 
 /**
diff --git a/Marlin/src/gcode/feature/clean/G12.cpp b/Marlin/src/gcode/feature/clean/G12.cpp
index bdfaf38a06cf0f736fff907a24988d161a616217..6337665d4cf2a19cefe6c28e74873ce597eac7c6 100644
--- a/Marlin/src/gcode/feature/clean/G12.cpp
+++ b/Marlin/src/gcode/feature/clean/G12.cpp
@@ -47,6 +47,13 @@ void GcodeSuite::G12() {
   // Don't allow nozzle cleaning without homing first
   if (axis_unhomed_error()) return;
 
+  #ifdef WIPE_SEQUENCE_COMMANDS
+    if (!parser.seen_any()) {
+      gcode.process_subcommands_now_P(PSTR(WIPE_SEQUENCE_COMMANDS));
+      return;
+    }
+  #endif
+
   const uint8_t pattern = parser.ushortval('P', 0),
                 strokes = parser.ushortval('S', NOZZLE_CLEAN_STROKES),
                 objects = parser.ushortval('T', NOZZLE_CLEAN_TRIANGLES);