diff --git a/commonmark/src/main/java/org/commonmark/internal/util/AsciiMatcher.java b/commonmark/src/main/java/org/commonmark/internal/util/AsciiMatcher.java
index 35769f82ddd47280816a95e33f5aea45274fb562..d31020fa37ea1343cc3dd425c673715eb52e0535 100644
--- a/commonmark/src/main/java/org/commonmark/internal/util/AsciiMatcher.java
+++ b/commonmark/src/main/java/org/commonmark/internal/util/AsciiMatcher.java
@@ -22,6 +22,10 @@ public class AsciiMatcher implements CharMatcher {
         return new Builder(new BitSet());
     }
 
+    public static Builder builder(AsciiMatcher matcher) {
+        return new Builder((BitSet) matcher.set.clone());
+    }
+
     public static class Builder {
         private final BitSet set;
 
diff --git a/commonmark/src/main/java/org/commonmark/renderer/markdown/CoreMarkdownNodeRenderer.java b/commonmark/src/main/java/org/commonmark/renderer/markdown/CoreMarkdownNodeRenderer.java
index fe5725aee3c958b5e246ddcc7f408a0777f7f8cc..8cb67e0fd25d5a2d466ec47a2f35cd94fa9d47cf 100644
--- a/commonmark/src/main/java/org/commonmark/renderer/markdown/CoreMarkdownNodeRenderer.java
+++ b/commonmark/src/main/java/org/commonmark/renderer/markdown/CoreMarkdownNodeRenderer.java
@@ -24,6 +24,8 @@ public class CoreMarkdownNodeRenderer extends AbstractVisitor implements NodeRen
 
     private final AsciiMatcher textEscape =
             AsciiMatcher.builder().anyOf("[]<>`*&").build();
+    private final CharMatcher textEscapeInHeading =
+            AsciiMatcher.builder(textEscape).anyOf("#").build();
     private final CharMatcher linkDestinationNeedsAngleBrackets =
             AsciiMatcher.builder().c(' ').c('(').c(')').c('<').c('>').c('\\').build();
     private final CharMatcher linkDestinationEscapeInAngleBrackets =
@@ -366,11 +368,13 @@ public class CoreMarkdownNodeRenderer extends AbstractVisitor implements NodeRen
             }
         }
 
+        CharMatcher escape = text.getParent() instanceof Heading ? textEscapeInHeading : textEscape;
+
         if (literal.endsWith("!") && text.getNext() instanceof Link) {
-            writer.writeEscaped(literal.substring(0, literal.length() - 1), textEscape);
+            writer.writeEscaped(literal.substring(0, literal.length() - 1), escape);
             writer.write("\\!");
         } else {
-            writer.writeEscaped(literal, textEscape);
+            writer.writeEscaped(literal, escape);
         }
     }
 
diff --git a/commonmark/src/test/java/org/commonmark/renderer/markdown/SpecMarkdownRendererTest.java b/commonmark/src/test/java/org/commonmark/renderer/markdown/SpecMarkdownRendererTest.java
index 632f4acfc786474c0933b79078ec4214f8dd3516..d6bdf9cfb0c709a26090eb2cade74a21cef05487 100644
--- a/commonmark/src/test/java/org/commonmark/renderer/markdown/SpecMarkdownRendererTest.java
+++ b/commonmark/src/test/java/org/commonmark/renderer/markdown/SpecMarkdownRendererTest.java
@@ -62,7 +62,7 @@ public class SpecMarkdownRendererTest {
             System.out.println();
         }
 
-        int expectedPassed = 646;
+        int expectedPassed = 647;
         assertTrue("Expected at least " + expectedPassed + " examples to pass but was " + passes.size(), passes.size() >= expectedPassed);
     }