diff --git a/paper-server/patches/sources/net/minecraft/world/entity/animal/Turtle.java.patch b/paper-server/patches/sources/net/minecraft/world/entity/animal/Turtle.java.patch
index b0412dae18..4b9ddbae38 100644
--- a/paper-server/patches/sources/net/minecraft/world/entity/animal/Turtle.java.patch
+++ b/paper-server/patches/sources/net/minecraft/world/entity/animal/Turtle.java.patch
@@ -19,16 +19,27 @@
      }
  
      @Override
-@@ -460,7 +462,7 @@
+@@ -446,6 +448,10 @@
+             if (entityplayer == null && this.partner.getLoveCause() != null) {
+                 entityplayer = this.partner.getLoveCause();
+             }
++            // Paper start - Add EntityFertilizeEggEvent event
++            io.papermc.paper.event.entity.EntityFertilizeEggEvent event = org.bukkit.craftbukkit.event.CraftEventFactory.callEntityFertilizeEggEvent(this.animal, this.partner);
++            if (event.isCancelled()) return;
++            // Paper end - Add EntityFertilizeEggEvent event
+ 
+             if (entityplayer != null) {
+                 entityplayer.awardStat(Stats.ANIMALS_BRED);
+@@ -460,7 +466,7 @@
              RandomSource randomsource = this.animal.getRandom();
  
              if (getServerLevel((Level) this.level).getGameRules().getBoolean(GameRules.RULE_DOMOBLOOT)) {
 -                this.level.addFreshEntity(new ExperienceOrb(this.level, this.animal.getX(), this.animal.getY(), this.animal.getZ(), randomsource.nextInt(7) + 1));
-+                this.level.addFreshEntity(new ExperienceOrb(this.level, this.animal.getX(), this.animal.getY(), this.animal.getZ(), randomsource.nextInt(7) + 1, org.bukkit.entity.ExperienceOrb.SpawnReason.BREED, entityplayer)); // Paper;
++                if (event.getExperience() > 0) this.level.addFreshEntity(new ExperienceOrb(this.level, this.animal.getX(), this.animal.getY(), this.animal.getZ(), event.getExperience(), org.bukkit.entity.ExperienceOrb.SpawnReason.BREED, entityplayer)); // Paper - Add EntityFertilizeEggEvent event
              }
  
          }
-@@ -492,16 +494,21 @@
+@@ -492,16 +498,21 @@
  
              if (!this.turtle.isInWater() && this.isReachedTarget()) {
                  if (this.turtle.layEggCounter < 1) {
@@ -52,7 +63,7 @@
                      this.turtle.setHasEgg(false);
                      this.turtle.setLayingEgg(false);
                      this.turtle.setInLoveTime(600);
-@@ -567,7 +574,7 @@
+@@ -567,7 +578,7 @@
  
          @Override
          public boolean canUse() {
diff --git a/paper-server/patches/sources/net/minecraft/world/entity/animal/frog/Frog.java.patch b/paper-server/patches/sources/net/minecraft/world/entity/animal/frog/Frog.java.patch
new file mode 100644
index 0000000000..f849bb1ffc
--- /dev/null
+++ b/paper-server/patches/sources/net/minecraft/world/entity/animal/frog/Frog.java.patch
@@ -0,0 +1,16 @@
+--- a/net/minecraft/world/entity/animal/frog/Frog.java
++++ b/net/minecraft/world/entity/animal/frog/Frog.java
+@@ -270,7 +270,12 @@
+ 
+     @Override
+     public void spawnChildFromBreeding(ServerLevel world, Animal other) {
+-        this.finalizeSpawnChildFromBreeding(world, other, null);
++        // Paper start - Add EntityFertilizeEggEvent event
++        final io.papermc.paper.event.entity.EntityFertilizeEggEvent result = org.bukkit.craftbukkit.event.CraftEventFactory.callEntityFertilizeEggEvent(this, other);
++        if (result.isCancelled()) return;
++
++        this.finalizeSpawnChildFromBreeding(world, other, null, result.getExperience()); // Paper - use craftbukkit call that takes experience amount
++        // Paper end - Add EntityFertilizeEggEvent event
+         this.getBrain().setMemory(MemoryModuleType.IS_PREGNANT, Unit.INSTANCE);
+     }
+ 
diff --git a/paper-server/patches/sources/net/minecraft/world/entity/animal/sniffer/Sniffer.java.patch b/paper-server/patches/sources/net/minecraft/world/entity/animal/sniffer/Sniffer.java.patch
index 8e752b40ac..a6567df470 100644
--- a/paper-server/patches/sources/net/minecraft/world/entity/animal/sniffer/Sniffer.java.patch
+++ b/paper-server/patches/sources/net/minecraft/world/entity/animal/sniffer/Sniffer.java.patch
@@ -23,10 +23,21 @@
          return this;
      }
  
-@@ -338,8 +345,9 @@
+@@ -333,13 +340,19 @@
+ 
+     @Override
+     public void spawnChildFromBreeding(ServerLevel world, Animal other) {
++        // Paper start - Add EntityFertilizeEggEvent event
++        final io.papermc.paper.event.entity.EntityFertilizeEggEvent result = org.bukkit.craftbukkit.event.CraftEventFactory.callEntityFertilizeEggEvent(this, other);
++        if (result.isCancelled()) return;
++        // Paper end - Add EntityFertilizeEggEvent event
++
+         ItemStack itemstack = new ItemStack(Items.SNIFFER_EGG);
+         ItemEntity entityitem = new ItemEntity(world, this.position().x(), this.position().y(), this.position().z(), itemstack);
  
          entityitem.setDefaultPickUpDelay();
-         this.finalizeSpawnChildFromBreeding(world, other, (AgeableMob) null);
+-        this.finalizeSpawnChildFromBreeding(world, other, (AgeableMob) null);
++        this.finalizeSpawnChildFromBreeding(world, other, (AgeableMob) null, result.getExperience()); // Paper - Add EntityFertilizeEggEvent event
 +        if (this.spawnAtLocation(world, entityitem) != null) { // Paper - Call EntityDropItemEvent
          this.playSound(SoundEvents.SNIFFER_EGG_PLOP, 1.0F, (this.random.nextFloat() - this.random.nextFloat()) * 0.2F + 0.5F);
 -        world.addFreshEntity(entityitem);
@@ -34,7 +45,7 @@
      }
  
      @Override
-@@ -444,7 +452,7 @@
+@@ -444,7 +457,7 @@
  
      @Override
      public Brain<Sniffer> getBrain() {
diff --git a/paper-server/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java b/paper-server/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java
index 48d39015da..ec5c16f64d 100644
--- a/paper-server/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java
+++ b/paper-server/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java
@@ -2195,4 +2195,28 @@ public class CraftEventFactory {
         return event.callEvent();
     }
     // Paper end
+
+    // Paper start - add EntityFertilizeEggEvent
+    /**
+     * Calls the {@link io.papermc.paper.event.entity.EntityFertilizeEggEvent}.
+     * If the event is cancelled, this method also resets the love on both the {@code breeding} and {@code other} entity.
+     *
+     * @param breeding the entity on which #spawnChildFromBreeding was called.
+     * @param other    the partner of the entity.
+     * @return the event after it was called. The instance may be used to retrieve the experience of the event.
+     */
+    public static io.papermc.paper.event.entity.EntityFertilizeEggEvent callEntityFertilizeEggEvent(Animal breeding, Animal other) {
+        ServerPlayer serverPlayer = breeding.getLoveCause();
+        if (serverPlayer == null) serverPlayer = other.getLoveCause();
+        final int experience = breeding.getRandom().nextInt(7) + 1; // From Animal#spawnChildFromBreeding(ServerLevel, Animal)
+
+        final io.papermc.paper.event.entity.EntityFertilizeEggEvent event = new io.papermc.paper.event.entity.EntityFertilizeEggEvent((LivingEntity) breeding.getBukkitEntity(), (LivingEntity) other.getBukkitEntity(), serverPlayer == null ? null : serverPlayer.getBukkitEntity(), breeding.breedItem == null ? null : CraftItemStack.asCraftMirror(breeding.breedItem).clone(), experience);
+        if (!event.callEvent()) {
+            breeding.resetLove();
+            other.resetLove(); // stop the pathfinding to avoid infinite loop
+        }
+
+        return event;
+    }
+    // Paper end - add EntityFertilizeEggEvent
 }