diff --git a/Marlin/Configuration.h b/Marlin/Configuration.h
index d528a97bf7..f904803cc1 100644
--- a/Marlin/Configuration.h
+++ b/Marlin/Configuration.h
@@ -1289,6 +1289,15 @@
  */
 //#define RESTORE_LEVELING_AFTER_G28
 
+/**
+ * Auto-leveling needs preheating
+ */
+//#define PREHEAT_BEFORE_LEVELING
+#if ENABLED(PREHEAT_BEFORE_LEVELING)
+  #define LEVELING_NOZZLE_TEMP 120
+  #define LEVELING_BED_TEMP     50
+#endif
+
 /**
  * Enable detailed logging of G28, G29, M48, etc.
  * Turn on with the command 'M111 S32'.
diff --git a/Marlin/src/gcode/bedlevel/abl/G29.cpp b/Marlin/src/gcode/bedlevel/abl/G29.cpp
index 05260955bf..157353c063 100644
--- a/Marlin/src/gcode/bedlevel/abl/G29.cpp
+++ b/Marlin/src/gcode/bedlevel/abl/G29.cpp
@@ -36,9 +36,12 @@
 #include "../../../module/probe.h"
 #include "../../queue.h"
 
+#if EITHER(PROBE_TEMP_COMPENSATION, PREHEAT_BEFORE_LEVELING)
+  #include "../../../module/temperature.h"
+#endif
+
 #if ENABLED(PROBE_TEMP_COMPENSATION)
   #include "../../../feature/probe_temp_comp.h"
-  #include "../../../module/temperature.h"
 #endif
 
 #if HAS_DISPLAY
@@ -403,6 +406,24 @@ G29_TYPE GcodeSuite::G29() {
 
     if (!faux) remember_feedrate_scaling_off();
 
+    #if ENABLED(PREHEAT_BEFORE_LEVELING)
+      #ifndef LEVELING_NOZZLE_TEMP
+        #define LEVELING_NOZZLE_TEMP 0
+      #endif
+      #ifndef LEVELING_BED_TEMP
+        #define LEVELING_BED_TEMP 0
+      #endif
+      if (!dryrun && !faux) {
+        constexpr uint16_t hotendPreheat = LEVELING_NOZZLE_TEMP, bedPreheat = LEVELING_BED_TEMP;
+        if (DEBUGGING(LEVELING))
+          DEBUG_ECHOLNPAIR("Preheating hotend (", hotendPreheat, ") and bed (", bedPreheat, ")");
+        if (hotendPreheat) thermalManager.setTargetHotend(hotendPreheat, 0);
+        if (bedPreheat)    thermalManager.setTargetBed(bedPreheat);
+        if (hotendPreheat) thermalManager.wait_for_hotend(0);
+        if (bedPreheat)    thermalManager.wait_for_bed_heating();
+      }
+    #endif
+
     // Disable auto bed leveling during G29.
     // Be formal so G29 can be done successively without G28.
     if (!no_action) set_bed_leveling_enabled(false);