diff --git a/app/src/main/java/eu/kanade/tachiyomi/data/download/DownloadManager.kt b/app/src/main/java/eu/kanade/tachiyomi/data/download/DownloadManager.kt
index 85c044750..374d92623 100644
--- a/app/src/main/java/eu/kanade/tachiyomi/data/download/DownloadManager.kt
+++ b/app/src/main/java/eu/kanade/tachiyomi/data/download/DownloadManager.kt
@@ -157,6 +157,20 @@ class DownloadManager(
         downloader.queueChapters(manga, chapters, autoStart)
     }
 
+    /**
+     * Tells the downloader to enqueue the given list of downloads at the start of the queue.
+     *
+     * @param downloads the list of downloads to enqueue.
+     */
+    fun addDownloadsToStartOfQueue(downloads: List<Download>) {
+        val wasEmpty = queue.isEmpty()
+        queue.toMutableList().apply {
+            addAll(0, downloads)
+            reorderQueue(this)
+        }
+        if (wasEmpty) startDownloads()
+    }
+
     /**
      * Builds the page list of a downloaded chapter.
      *
diff --git a/app/src/main/java/eu/kanade/tachiyomi/data/preference/PreferencesHelper.kt b/app/src/main/java/eu/kanade/tachiyomi/data/preference/PreferencesHelper.kt
index 82a1e6522..ee5aaf811 100644
--- a/app/src/main/java/eu/kanade/tachiyomi/data/preference/PreferencesHelper.kt
+++ b/app/src/main/java/eu/kanade/tachiyomi/data/preference/PreferencesHelper.kt
@@ -275,11 +275,13 @@ class PreferencesHelper(val context: Context) {
 
     fun pinnedSources() = flowPrefs.getStringSet("pinned_catalogues", emptySet())
 
-    fun downloadNewChapter() = flowPrefs.getBoolean("download_new", false)
+    fun downloadNewChapters() = flowPrefs.getBoolean("download_new", false)
 
     fun downloadNewChapterCategories() = flowPrefs.getStringSet("download_new_categories", emptySet())
     fun downloadNewChapterCategoriesExclude() = flowPrefs.getStringSet("download_new_categories_exclude", emptySet())
 
+    fun autoDownloadWhileReading() = flowPrefs.getInt("auto_download_while_reading", 0)
+
     fun defaultCategory() = prefs.getInt(Keys.defaultCategory, -1)
 
     fun categorizedDisplaySettings() = flowPrefs.getBoolean("categorized_display", false)
diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/reader/ReaderPresenter.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/reader/ReaderPresenter.kt
index 902e31385..3095bf84a 100644
--- a/app/src/main/java/eu/kanade/tachiyomi/ui/reader/ReaderPresenter.kt
+++ b/app/src/main/java/eu/kanade/tachiyomi/ui/reader/ReaderPresenter.kt
@@ -19,8 +19,10 @@ import eu.kanade.domain.track.interactor.GetTracks
 import eu.kanade.domain.track.interactor.InsertTrack
 import eu.kanade.domain.track.model.toDbTrack
 import eu.kanade.tachiyomi.data.database.models.Manga
+import eu.kanade.tachiyomi.data.database.models.toDomainChapter
 import eu.kanade.tachiyomi.data.database.models.toDomainManga
 import eu.kanade.tachiyomi.data.download.DownloadManager
+import eu.kanade.tachiyomi.data.download.model.Download
 import eu.kanade.tachiyomi.data.preference.PreferencesHelper
 import eu.kanade.tachiyomi.data.saver.Image
 import eu.kanade.tachiyomi.data.saver.ImageSaver
@@ -32,6 +34,7 @@ import eu.kanade.tachiyomi.source.SourceManager
 import eu.kanade.tachiyomi.source.model.Page
 import eu.kanade.tachiyomi.ui.base.presenter.BasePresenter
 import eu.kanade.tachiyomi.ui.reader.loader.ChapterLoader
+import eu.kanade.tachiyomi.ui.reader.loader.DownloadPageLoader
 import eu.kanade.tachiyomi.ui.reader.loader.HttpPageLoader
 import eu.kanade.tachiyomi.ui.reader.model.InsertPage
 import eu.kanade.tachiyomi.ui.reader.model.ReaderChapter
@@ -63,6 +66,7 @@ import uy.kohesive.injekt.injectLazy
 import java.util.Date
 import java.util.concurrent.TimeUnit
 import eu.kanade.domain.manga.model.Manga as DomainManga
+import eu.kanade.tachiyomi.data.database.models.Chapter as DbChapter
 
 /**
  * Presenter used by the activity to perform background operations.
@@ -119,6 +123,8 @@ class ReaderPresenter(
 
     private val imageSaver: ImageSaver by injectLazy()
 
+    private var chapterDownload: Download? = null
+
     /**
      * Chapter list for the active manga. It's retrieved lazily and should be accessed for the first
      * time in a background thread to avoid blocking the UI.
@@ -191,6 +197,9 @@ class ReaderPresenter(
         if (currentChapters != null) {
             currentChapters.unref()
             saveReadingProgress(currentChapters.currChapter)
+            chapterDownload?.let {
+                downloadManager.addDownloadsToStartOfQueue(listOf(it))
+            }
         }
     }
 
@@ -318,6 +327,7 @@ class ReaderPresenter(
                 newChapters.ref()
                 oldChapters?.unref()
 
+                chapterDownload = deleteChapterFromDownloadQueue(newChapters.currChapter)
                 viewerChaptersRelay.call(newChapters)
             }
     }
@@ -416,7 +426,6 @@ class ReaderPresenter(
             selectedChapter.chapter.read = true
             updateTrackChapterRead(selectedChapter)
             deleteChapterIfNeeded(selectedChapter)
-            deleteChapterFromDownloadQueue(currentChapters.currChapter)
         }
 
         if (selectedChapter != currentChapters.currChapter) {
@@ -425,15 +434,56 @@ class ReaderPresenter(
             setReadStartTime()
             loadNewChapter(selectedChapter)
         }
+        val pages = page.chapter.pages ?: return
+        val inDownloadRange = page.number.toDouble() / pages.size > 0.2
+        if (inDownloadRange) {
+            downloadNextChapters()
+        }
+    }
+
+    private fun downloadNextChapters() {
+        val manga = manga ?: return
+        if (getCurrentChapter()?.pageLoader !is DownloadPageLoader) return
+        val nextChapter = viewerChaptersRelay.value?.nextChapter?.chapter ?: return
+        val chaptersNumberToDownload = preferences.autoDownloadWhileReading().get()
+        if (chaptersNumberToDownload == 0 || !manga.favorite) return
+        val isNextChapterDownloaded =
+            downloadManager.isChapterDownloaded(nextChapter.name, nextChapter.scanlator, manga.title, manga.source)
+        if (isNextChapterDownloaded) {
+            downloadAutoNextChapters(chaptersNumberToDownload, nextChapter.id)
+        }
+    }
+
+    private fun downloadAutoNextChapters(choice: Int, nextChapterId: Long?) {
+        val chaptersToDownload = getNextUnreadChaptersSorted(nextChapterId).take(choice - 1)
+        if (chaptersToDownload.isNotEmpty()) {
+            downloadChapters(chaptersToDownload)
+        }
+    }
+
+    private fun getNextUnreadChaptersSorted(nextChapterId: Long?): List<DbChapter> {
+        return chapterList.map { it.chapter.toDomainChapter()!! }
+            .filter { !it.read || it.id == nextChapterId }
+            .sortedWith(getChapterSort(manga?.toDomainManga()!!, false))
+            .map { it.toDbChapter() }
+            .takeLastWhile { it.id != nextChapterId }
+    }
+
+    /**
+     * Downloads the given list of chapters with the manager.
+     * @param chapters the list of chapters to download.
+     */
+    private fun downloadChapters(chapters: List<DbChapter>) {
+        downloadManager.downloadChapters(manga?.toDomainManga()!!, chapters)
     }
 
     /**
      * Removes [currentChapter] from download queue
      * if setting is enabled and [currentChapter] is queued for download
      */
-    private fun deleteChapterFromDownloadQueue(currentChapter: ReaderChapter) {
-        downloadManager.getChapterDownloadOrNull(currentChapter.chapter)?.let { download ->
-            downloadManager.deletePendingDownload(download)
+    private fun deleteChapterFromDownloadQueue(currentChapter: ReaderChapter): Download? {
+        return downloadManager.getChapterDownloadOrNull(currentChapter.chapter)?.apply {
+            downloadManager.deletePendingDownload(this)
         }
     }
 
@@ -448,6 +498,9 @@ class ReaderPresenter(
         val removeAfterReadSlots = preferences.removeAfterReadSlots()
         val chapterToDelete = chapterList.getOrNull(currentChapterPosition - removeAfterReadSlots)
 
+        if (removeAfterReadSlots != 0 && chapterDownload != null) {
+            downloadManager.addDownloadsToStartOfQueue(listOf(chapterDownload!!))
+        }
         // Check if deleting option is enabled and chapter exists
         if (removeAfterReadSlots != -1 && chapterToDelete != null) {
             enqueueDeleteReadChapters(chapterToDelete)
diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/setting/SettingsDownloadController.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/setting/SettingsDownloadController.kt
index da41c8933..c0b7ad20f 100644
--- a/app/src/main/java/eu/kanade/tachiyomi/ui/setting/SettingsDownloadController.kt
+++ b/app/src/main/java/eu/kanade/tachiyomi/ui/setting/SettingsDownloadController.kt
@@ -19,6 +19,7 @@ import eu.kanade.tachiyomi.ui.base.controller.DialogController
 import eu.kanade.tachiyomi.util.preference.bindTo
 import eu.kanade.tachiyomi.util.preference.defaultValue
 import eu.kanade.tachiyomi.util.preference.entriesRes
+import eu.kanade.tachiyomi.util.preference.infoPreference
 import eu.kanade.tachiyomi.util.preference.intListPreference
 import eu.kanade.tachiyomi.util.preference.multiSelectListPreference
 import eu.kanade.tachiyomi.util.preference.onClick
@@ -129,10 +130,10 @@ class SettingsDownloadController : SettingsController() {
         }
 
         preferenceCategory {
-            titleRes = R.string.pref_category_auto_download
+            titleRes = R.string.pref_download_new
 
             switchPreference {
-                bindTo(preferences.downloadNewChapter())
+                bindTo(preferences.downloadNewChapters())
                 titleRes = R.string.pref_download_new
             }
             preference {
@@ -142,7 +143,7 @@ class SettingsDownloadController : SettingsController() {
                     DownloadCategoriesDialog().showDialog(router)
                 }
 
-                visibleIf(preferences.downloadNewChapter()) { it }
+                visibleIf(preferences.downloadNewChapters()) { it }
 
                 fun updateSummary() {
                     val selectedCategories = preferences.downloadNewChapterCategories().get()
@@ -178,6 +179,25 @@ class SettingsDownloadController : SettingsController() {
                     .launchIn(viewScope)
             }
         }
+
+        preferenceCategory {
+            titleRes = R.string.download_ahead
+
+            intListPreference {
+                bindTo(preferences.autoDownloadWhileReading())
+                titleRes = R.string.auto_download_while_reading
+                entries = arrayOf(
+                    context.getString(R.string.disabled),
+                    context.resources.getQuantityString(R.plurals.next_unread_chapters, 2, 2),
+                    context.resources.getQuantityString(R.plurals.next_unread_chapters, 3, 3),
+                    context.resources.getQuantityString(R.plurals.next_unread_chapters, 5, 5),
+                    context.resources.getQuantityString(R.plurals.next_unread_chapters, 10, 10),
+                )
+                entryValues = arrayOf("0", "2", "3", "5", "10")
+                summary = "%s"
+            }
+            infoPreference(R.string.download_ahead_info)
+        }
     }
 
     override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
diff --git a/app/src/main/java/eu/kanade/tachiyomi/util/MangaExtensions.kt b/app/src/main/java/eu/kanade/tachiyomi/util/MangaExtensions.kt
index 76089f437..03a2b202c 100644
--- a/app/src/main/java/eu/kanade/tachiyomi/util/MangaExtensions.kt
+++ b/app/src/main/java/eu/kanade/tachiyomi/util/MangaExtensions.kt
@@ -57,8 +57,8 @@ fun DomainManga.shouldDownloadNewChapters(dbCategories: List<Long>, preferences:
     val categories = dbCategories.ifEmpty { listOf(0L) }
 
     // Boolean to determine if user wants to automatically download new chapters.
-    val downloadNewChapter = preferences.downloadNewChapter().get()
-    if (!downloadNewChapter) return false
+    val downloadNewChapters = preferences.downloadNewChapters().get()
+    if (!downloadNewChapters) return false
 
     val includedCategories = preferences.downloadNewChapterCategories().get().map { it.toLong() }
     val excludedCategories = preferences.downloadNewChapterCategoriesExclude().get().map { it.toLong() }
diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml
index 013f61eb5..f633ebf44 100644
--- a/app/src/main/res/values/strings.xml
+++ b/app/src/main/res/values/strings.xml
@@ -417,11 +417,18 @@
     <string name="pref_category_auto_download">Auto-download</string>
     <string name="pref_download_new">Download new chapters</string>
     <string name="pref_download_new_categories_details">Manga in excluded categories will not be downloaded even if they are also in included categories.</string>
+    <string name="download_ahead">Download ahead</string>
+    <string name="auto_download_while_reading">Auto download while reading</string>
+    <plurals name="next_unread_chapters">
+        <item quantity="one">Next unread chapter</item>
+        <item quantity="other">Next %d unread chapters</item>
+    </plurals>
+    <string name="download_ahead_info">Only works on entries in library and if the current chapter plus the next one are already downloaded</string>
     <string name="save_chapter_as_cbz">Save as CBZ archive</string>
     <string name="split_tall_images">Split tall images</string>
     <string name="split_tall_images_summary">Improves reader performance</string>
 
-      <!-- Tracking section -->
+    <!-- Tracking section -->
     <string name="tracking_guide">Tracking guide</string>
     <string name="pref_auto_update_manga_sync">Update progress after reading</string>
     <string name="services">Services</string>