diff --git a/multisrc/overrides/heancms/reaperscans/src/ReaperScans.kt b/multisrc/overrides/heancms/reaperscans/src/ReaperScans.kt
index 89a6c1027..d382dfcb7 100644
--- a/multisrc/overrides/heancms/reaperscans/src/ReaperScans.kt
+++ b/multisrc/overrides/heancms/reaperscans/src/ReaperScans.kt
@@ -1,21 +1,10 @@
 package eu.kanade.tachiyomi.extension.pt.reaperscans
 
 import eu.kanade.tachiyomi.multisrc.heancms.Genre
-import eu.kanade.tachiyomi.multisrc.heancms.GenreFilter
 import eu.kanade.tachiyomi.multisrc.heancms.HeanCms
-import eu.kanade.tachiyomi.multisrc.heancms.HeanCmsSeriesDto
-import eu.kanade.tachiyomi.multisrc.heancms.SortByFilter
-import eu.kanade.tachiyomi.multisrc.heancms.StatusFilter
-import eu.kanade.tachiyomi.network.GET
 import eu.kanade.tachiyomi.network.interceptor.rateLimitHost
-import eu.kanade.tachiyomi.source.model.FilterList
-import eu.kanade.tachiyomi.source.model.Page
-import eu.kanade.tachiyomi.source.model.SChapter
-import eu.kanade.tachiyomi.util.asJsoup
 import okhttp3.HttpUrl.Companion.toHttpUrl
 import okhttp3.OkHttpClient
-import okhttp3.Request
-import okhttp3.Response
 import java.text.SimpleDateFormat
 import java.util.TimeZone
 
@@ -32,87 +21,15 @@ class ReaperScans : HeanCms(
     // Site changed from Madara to HeanCms.
     override val versionId = 2
 
+    override val fetchAllTitles = true
+    override val useNewQueryEndpoint = true
+
     override val coverPath: String = ""
 
     override val dateFormat: SimpleDateFormat = super.dateFormat.apply {
         timeZone = TimeZone.getTimeZone("GMT+01:00")
     }
 
-    override fun popularMangaRequest(page: Int): Request {
-        val url = "$apiUrl/query".toHttpUrl().newBuilder()
-            .addQueryParameter("query_string", "")
-            .addQueryParameter("series_status", "All")
-            .addQueryParameter("order", "desc")
-            .addQueryParameter("orderBy", "total_views")
-            .addQueryParameter("series_type", "Comic")
-            .addQueryParameter("page", page.toString())
-            .addQueryParameter("perPage", "12")
-            .addQueryParameter("tags_ids", "[]")
-
-        return GET(url.build(), headers)
-    }
-
-    override fun latestUpdatesRequest(page: Int): Request {
-        val url = "$apiUrl/query".toHttpUrl().newBuilder()
-            .addQueryParameter("query_string", "")
-            .addQueryParameter("series_status", "All")
-            .addQueryParameter("order", "desc")
-            .addQueryParameter("orderBy", "latest")
-            .addQueryParameter("series_type", "Comic")
-            .addQueryParameter("page", page.toString())
-            .addQueryParameter("perPage", "12")
-            .addQueryParameter("tags_ids", "[]")
-
-        return GET(url.build(), headers)
-    }
-
-    override fun searchMangaRequest(page: Int, query: String, filters: FilterList): Request {
-        val sortByFilter = filters.firstInstanceOrNull<SortByFilter>()
-        val statusFilter = filters.firstInstanceOrNull<StatusFilter>()
-
-        val tagIds = filters.firstInstanceOrNull<GenreFilter>()?.state.orEmpty()
-            .filter(Genre::state)
-            .map(Genre::id)
-            .joinToString(",", prefix = "[", postfix = "]")
-
-        val url = "$apiUrl/query".toHttpUrl().newBuilder()
-            .addQueryParameter("query_string", query)
-            .addQueryParameter("series_status", statusFilter?.selected?.value ?: "All")
-            .addQueryParameter("order", if (sortByFilter?.state?.ascending == true) "asc" else "desc")
-            .addQueryParameter("orderBy", sortByFilter?.selected ?: "total_views")
-            .addQueryParameter("series_type", "Comic")
-            .addQueryParameter("page", page.toString())
-            .addQueryParameter("perPage", "12")
-            .addQueryParameter("tags_ids", tagIds)
-
-        return GET(url.build(), headers)
-    }
-
-    override fun chapterListParse(response: Response): List<SChapter> {
-        val result = response.parseAs<HeanCmsSeriesDto>()
-
-        val currentTimestamp = System.currentTimeMillis()
-
-        return result.seasons.orEmpty()
-            .flatMap { it.chapters.orEmpty() }
-            .filterNot { it.price == 1 }
-            .map { it.toSChapter(result.slug, dateFormat) }
-            .filter { it.date_upload <= currentTimestamp }
-    }
-
-    override fun pageListRequest(chapter: SChapter) = GET(baseUrl + chapter.url, headers)
-
-    override fun pageListParse(response: Response): List<Page> {
-        val document = response.asJsoup()
-
-        val images = document.selectFirst("div.min-h-screen > div.container > p.items-center")
-
-        return images?.select("img").orEmpty().mapIndexed { i, img ->
-            val imageUrl = if (img.hasClass("lazy")) img.absUrl("data-src") else img.absUrl("src")
-            Page(i, "", imageUrl)
-        }
-    }
-
     override fun getGenreList(): List<Genre> = listOf(
         Genre("Artes Marciais", 2),
         Genre("Aventura", 10),
diff --git a/multisrc/overrides/heancms/yugenmangas/src/YugenMangas.kt b/multisrc/overrides/heancms/yugenmangas/src/YugenMangas.kt
index 6dbc15f89..83038a2ca 100644
--- a/multisrc/overrides/heancms/yugenmangas/src/YugenMangas.kt
+++ b/multisrc/overrides/heancms/yugenmangas/src/YugenMangas.kt
@@ -1,20 +1,9 @@
 package eu.kanade.tachiyomi.extension.es.yugenmangas
 
 import eu.kanade.tachiyomi.multisrc.heancms.Genre
-import eu.kanade.tachiyomi.multisrc.heancms.GenreFilter
 import eu.kanade.tachiyomi.multisrc.heancms.HeanCms
-import eu.kanade.tachiyomi.multisrc.heancms.HeanCmsSeriesDto
-import eu.kanade.tachiyomi.multisrc.heancms.SortByFilter
-import eu.kanade.tachiyomi.multisrc.heancms.StatusFilter
-import eu.kanade.tachiyomi.network.GET
 import eu.kanade.tachiyomi.network.interceptor.rateLimitHost
-import eu.kanade.tachiyomi.source.model.FilterList
-import eu.kanade.tachiyomi.source.model.Page
-import eu.kanade.tachiyomi.source.model.SChapter
-import eu.kanade.tachiyomi.util.asJsoup
 import okhttp3.HttpUrl.Companion.toHttpUrl
-import okhttp3.Request
-import okhttp3.Response
 import java.text.SimpleDateFormat
 import java.util.TimeZone
 import java.util.concurrent.TimeUnit
@@ -30,6 +19,9 @@ class YugenMangas :
     // Site changed from Madara to HeanCms.
     override val versionId = 2
 
+    override val fetchAllTitles = true
+    override val useNewQueryEndpoint = true
+
     override val client = super.client.newBuilder()
         .connectTimeout(60, TimeUnit.SECONDS)
         .readTimeout(90, TimeUnit.SECONDS)
@@ -42,81 +34,6 @@ class YugenMangas :
         timeZone = TimeZone.getTimeZone("UTC")
     }
 
-    override fun popularMangaRequest(page: Int): Request {
-        val url = "$apiUrl/query".toHttpUrl().newBuilder()
-            .addQueryParameter("query_string", "")
-            .addQueryParameter("series_status", "All")
-            .addQueryParameter("order", "desc")
-            .addQueryParameter("orderBy", "total_views")
-            .addQueryParameter("series_type", "Comic")
-            .addQueryParameter("page", page.toString())
-            .addQueryParameter("perPage", "12")
-            .addQueryParameter("tags_ids", "[]")
-
-        return GET(url.build(), headers)
-    }
-
-    override fun latestUpdatesRequest(page: Int): Request {
-        val url = "$apiUrl/query".toHttpUrl().newBuilder()
-            .addQueryParameter("query_string", "")
-            .addQueryParameter("series_status", "All")
-            .addQueryParameter("order", "desc")
-            .addQueryParameter("orderBy", "latest")
-            .addQueryParameter("series_type", "Comic")
-            .addQueryParameter("page", page.toString())
-            .addQueryParameter("perPage", "12")
-            .addQueryParameter("tags_ids", "[]")
-
-        return GET(url.build(), headers)
-    }
-
-    override fun searchMangaRequest(page: Int, query: String, filters: FilterList): Request {
-        val sortByFilter = filters.firstInstanceOrNull<SortByFilter>()
-        val statusFilter = filters.firstInstanceOrNull<StatusFilter>()
-
-        val tagIds = filters.firstInstanceOrNull<GenreFilter>()?.state.orEmpty()
-            .filter(Genre::state)
-            .map(Genre::id)
-            .joinToString(",", prefix = "[", postfix = "]")
-
-        val url = "$apiUrl/query".toHttpUrl().newBuilder()
-            .addQueryParameter("query_string", query)
-            .addQueryParameter("series_status", statusFilter?.selected?.value ?: "All")
-            .addQueryParameter("order", if (sortByFilter?.state?.ascending == true) "asc" else "desc")
-            .addQueryParameter("orderBy", sortByFilter?.selected ?: "total_views")
-            .addQueryParameter("series_type", "Comic")
-            .addQueryParameter("page", page.toString())
-            .addQueryParameter("perPage", "12")
-            .addQueryParameter("tags_ids", tagIds)
-
-        return GET(url.build(), headers)
-    }
-
-    override fun chapterListParse(response: Response): List<SChapter> {
-        val result = response.parseAs<HeanCmsSeriesDto>()
-
-        val currentTimestamp = System.currentTimeMillis()
-
-        return result.seasons.orEmpty()
-            .flatMap { it.chapters.orEmpty() }
-            .filterNot { it.price == 1 }
-            .map { it.toSChapter(result.slug, dateFormat) }
-            .filter { it.date_upload <= currentTimestamp }
-    }
-
-    override fun pageListRequest(chapter: SChapter) = GET(baseUrl + chapter.url, headers)
-
-    override fun pageListParse(response: Response): List<Page> {
-        val document = response.asJsoup()
-
-        val images = document.selectFirst("div.min-h-screen > div.container > p.items-center")
-
-        return images?.select("img").orEmpty().mapIndexed { i, img ->
-            val imageUrl = if (img.hasClass("lazy")) img.absUrl("data-src") else img.absUrl("src")
-            Page(i, "", imageUrl)
-        }
-    }
-
     override fun getGenreList(): List<Genre> = listOf(
         Genre("+18", 1),
         Genre("Acción", 36),
diff --git a/multisrc/src/main/java/eu/kanade/tachiyomi/multisrc/heancms/HeanCms.kt b/multisrc/src/main/java/eu/kanade/tachiyomi/multisrc/heancms/HeanCms.kt
index e1cdce178..f644777f1 100644
--- a/multisrc/src/main/java/eu/kanade/tachiyomi/multisrc/heancms/HeanCms.kt
+++ b/multisrc/src/main/java/eu/kanade/tachiyomi/multisrc/heancms/HeanCms.kt
@@ -9,10 +9,12 @@ import eu.kanade.tachiyomi.source.model.Page
 import eu.kanade.tachiyomi.source.model.SChapter
 import eu.kanade.tachiyomi.source.model.SManga
 import eu.kanade.tachiyomi.source.online.HttpSource
+import eu.kanade.tachiyomi.util.asJsoup
 import kotlinx.serialization.decodeFromString
 import kotlinx.serialization.encodeToString
 import kotlinx.serialization.json.Json
 import okhttp3.Headers
+import okhttp3.HttpUrl.Companion.toHttpUrl
 import okhttp3.MediaType.Companion.toMediaType
 import okhttp3.OkHttpClient
 import okhttp3.Request
@@ -33,6 +35,12 @@ abstract class HeanCms(
 
     override val client: OkHttpClient = network.cloudflareClient
 
+    protected open val fetchAllTitles = false
+
+    protected open val useNewQueryEndpoint = false
+
+    private var seriesSlugMap: Map<String, HeanCmsTitle>? = null
+
     /**
      * Custom Json instance to make usage of `encodeDefaults`,
      * which is not enabled on the injected instance of the app.
@@ -54,6 +62,10 @@ abstract class HeanCms(
         .add("Referer", "$baseUrl/")
 
     override fun popularMangaRequest(page: Int): Request {
+        if (useNewQueryEndpoint) {
+            return newEndpointPopularMangaRequest(page)
+        }
+
         val payloadObj = HeanCmsQuerySearchPayloadDto(
             page = page,
             order = "desc",
@@ -72,23 +84,45 @@ abstract class HeanCms(
         return POST("$apiUrl/series/querysearch", apiHeaders, payload)
     }
 
+    protected fun newEndpointPopularMangaRequest(page: Int): Request {
+        val url = "$apiUrl/query".toHttpUrl().newBuilder()
+            .addQueryParameter("query_string", "")
+            .addQueryParameter("series_status", "All")
+            .addQueryParameter("order", "desc")
+            .addQueryParameter("orderBy", "total_views")
+            .addQueryParameter("series_type", "Comic")
+            .addQueryParameter("page", page.toString())
+            .addQueryParameter("perPage", "12")
+            .addQueryParameter("tags_ids", "[]")
+
+        return GET(url.build(), headers)
+    }
+
     override fun popularMangaParse(response: Response): MangasPage {
         val json = response.body.string()
 
         if (json.startsWith("{")) {
             val result = json.parseAs<HeanCmsQuerySearchDto>()
-            val mangaList = result.data.map { it.toSManga(apiUrl, coverPath) }
+            val mangaList = result.data.map { it.toSManga(apiUrl, coverPath, fetchAllTitles) }
+
+            fetchAllTitles()
 
             return MangasPage(mangaList, result.meta?.hasNextPage ?: false)
         }
 
         val mangaList = json.parseAs<List<HeanCmsSeriesDto>>()
-            .map { it.toSManga(apiUrl, coverPath) }
+            .map { it.toSManga(apiUrl, coverPath, fetchAllTitles) }
+
+        fetchAllTitles()
 
         return MangasPage(mangaList, hasNextPage = false)
     }
 
     override fun latestUpdatesRequest(page: Int): Request {
+        if (useNewQueryEndpoint) {
+            return newEndpointLatestUpdatesRequest(page)
+        }
+
         val payloadObj = HeanCmsQuerySearchPayloadDto(
             page = page,
             order = "desc",
@@ -107,6 +141,20 @@ abstract class HeanCms(
         return POST("$apiUrl/series/querysearch", apiHeaders, payload)
     }
 
+    protected fun newEndpointLatestUpdatesRequest(page: Int): Request {
+        val url = "$apiUrl/query".toHttpUrl().newBuilder()
+            .addQueryParameter("query_string", "")
+            .addQueryParameter("series_status", "All")
+            .addQueryParameter("order", "desc")
+            .addQueryParameter("orderBy", "latest")
+            .addQueryParameter("series_type", "Comic")
+            .addQueryParameter("page", page.toString())
+            .addQueryParameter("perPage", "12")
+            .addQueryParameter("tags_ids", "[]")
+
+        return GET(url.build(), headers)
+    }
+
     override fun latestUpdatesParse(response: Response): MangasPage = popularMangaParse(response)
 
     override fun fetchSearchManga(page: Int, query: String, filters: FilterList): Observable<MangasPage> {
@@ -121,6 +169,10 @@ abstract class HeanCms(
     }
 
     override fun searchMangaRequest(page: Int, query: String, filters: FilterList): Request {
+        if (useNewQueryEndpoint) {
+            return newEndpointSearchMangaRequest(page, query, filters)
+        }
+
         if (query.isNotBlank()) {
             val searchPayloadObj = HeanCmsSearchPayloadDto(query)
             val searchPayload = json.encodeToString(searchPayloadObj)
@@ -158,16 +210,40 @@ abstract class HeanCms(
         return POST("$apiUrl/series/querysearch", apiHeaders, payload)
     }
 
+    protected fun newEndpointSearchMangaRequest(page: Int, query: String, filters: FilterList): Request {
+        val sortByFilter = filters.firstInstanceOrNull<SortByFilter>()
+        val statusFilter = filters.firstInstanceOrNull<StatusFilter>()
+
+        val tagIds = filters.firstInstanceOrNull<GenreFilter>()?.state.orEmpty()
+            .filter(Genre::state)
+            .map(Genre::id)
+            .joinToString(",", prefix = "[", postfix = "]")
+
+        val url = "$apiUrl/query".toHttpUrl().newBuilder()
+            .addQueryParameter("query_string", query)
+            .addQueryParameter("series_status", statusFilter?.selected?.value ?: "All")
+            .addQueryParameter("order", if (sortByFilter?.state?.ascending == true) "asc" else "desc")
+            .addQueryParameter("orderBy", sortByFilter?.selected ?: "total_views")
+            .addQueryParameter("series_type", "Comic")
+            .addQueryParameter("page", page.toString())
+            .addQueryParameter("perPage", "12")
+            .addQueryParameter("tags_ids", tagIds)
+
+        return GET(url.build(), headers)
+    }
+
     override fun searchMangaParse(response: Response): MangasPage {
         val json = response.body.string()
 
         if (response.request.url.pathSegments.last() == "search") {
+            fetchAllTitles()
+
             val result = json.parseAs<List<HeanCmsSearchDto>>()
             val mangaList = result
                 .filter { it.type == "Comic" }
                 .map {
                     it.slug = it.slug.replace(TIMESTAMP_REGEX, "")
-                    it.toSManga(apiUrl, coverPath)
+                    it.toSManga(apiUrl, coverPath, seriesSlugMap.orEmpty(), fetchAllTitles)
                 }
 
             return MangasPage(mangaList, false)
@@ -175,28 +251,51 @@ abstract class HeanCms(
 
         if (json.startsWith("{")) {
             val result = json.parseAs<HeanCmsQuerySearchDto>()
-            val mangaList = result.data.map { it.toSManga(apiUrl, coverPath) }
+            val mangaList = result.data.map { it.toSManga(apiUrl, coverPath, fetchAllTitles) }
+
+            fetchAllTitles()
 
             return MangasPage(mangaList, result.meta?.hasNextPage ?: false)
         }
 
         val mangaList = json.parseAs<List<HeanCmsSeriesDto>>()
-            .map { it.toSManga(apiUrl, coverPath) }
+            .map { it.toSManga(apiUrl, coverPath, fetchAllTitles) }
+
+        fetchAllTitles()
 
         return MangasPage(mangaList, hasNextPage = false)
     }
 
-    override fun getMangaUrl(manga: SManga) = baseUrl + manga.url
-
-    override fun mangaDetailsRequest(manga: SManga): Request {
+    override fun getMangaUrl(manga: SManga): String {
         val seriesSlug = manga.url
             .substringAfterLast("/")
+            .toPermSlugIfNeeded()
+
+        val currentSlug = seriesSlugMap?.get(seriesSlug)?.slug ?: seriesSlug
+
+        return "$baseUrl/series/$currentSlug"
+    }
+
+    override fun mangaDetailsRequest(manga: SManga): Request {
+        if (fetchAllTitles && manga.url.contains(TIMESTAMP_REGEX)) {
+            throw Exception(intl.urlChangedError(name))
+        }
+
+        val seriesSlug = manga.url
+            .substringAfterLast("/")
+            .toPermSlugIfNeeded()
+
+        fetchAllTitles()
+
+        val seriesDetails = seriesSlugMap?.get(seriesSlug)
+        val currentSlug = seriesDetails?.slug ?: seriesSlug
+        val currentStatus = seriesDetails?.status ?: manga.status
 
         val apiHeaders = headersBuilder()
             .add("Accept", ACCEPT_JSON)
             .build()
 
-        return GET("$apiUrl/series/$seriesSlug#${manga.status}", apiHeaders)
+        return GET("$apiUrl/series/$currentSlug#$currentStatus", apiHeaders)
     }
 
     override fun mangaDetailsParse(response: Response): SManga {
@@ -204,7 +303,7 @@ abstract class HeanCms(
 
         val result = runCatching { response.parseAs<HeanCmsSeriesDto>() }
 
-        val seriesDetails = result.getOrNull()?.toSManga(apiUrl, coverPath)
+        val seriesDetails = result.getOrNull()?.toSManga(apiUrl, coverPath, fetchAllTitles)
             ?: throw Exception(intl.urlChangedError(name))
 
         return seriesDetails.apply {
@@ -220,6 +319,14 @@ abstract class HeanCms(
 
         val currentTimestamp = System.currentTimeMillis()
 
+        if (useNewQueryEndpoint) {
+            return result.seasons.orEmpty()
+                .flatMap { it.chapters.orEmpty() }
+                .filterNot { it.price == 1 }
+                .map { it.toSChapter(result.slug, dateFormat) }
+                .filter { it.date_upload <= currentTimestamp }
+        }
+
         return result.chapters.orEmpty()
             .filterNot { it.price == 1 }
             .map { it.toSChapter(result.slug, dateFormat) }
@@ -230,6 +337,10 @@ abstract class HeanCms(
     override fun getChapterUrl(chapter: SChapter): String = baseUrl + chapter.url
 
     override fun pageListRequest(chapter: SChapter): Request {
+        if (useNewQueryEndpoint) {
+            return GET(baseUrl + chapter.url, headers)
+        }
+
         val chapterId = chapter.url.substringAfterLast("#")
 
         val apiHeaders = headersBuilder()
@@ -240,6 +351,17 @@ abstract class HeanCms(
     }
 
     override fun pageListParse(response: Response): List<Page> {
+        if (useNewQueryEndpoint) {
+            val document = response.asJsoup()
+
+            val images = document.selectFirst("div.min-h-screen > div.container > p.items-center")
+
+            return images?.select("img").orEmpty().mapIndexed { i, img ->
+                val imageUrl = if (img.hasClass("lazy")) img.absUrl("data-src") else img.absUrl("src")
+                Page(i, "", imageUrl)
+            }
+        }
+
         return response.parseAs<HeanCmsReaderDto>().content?.images.orEmpty()
             .filterNot { imageUrl ->
                 // Their image server returns HTTP 403 for hidden files that starts
@@ -266,6 +388,94 @@ abstract class HeanCms(
         return GET(page.imageUrl!!, imageHeaders)
     }
 
+    protected open fun fetchAllTitles() {
+        if (!seriesSlugMap.isNullOrEmpty() || !fetchAllTitles) {
+            return
+        }
+
+        val result = runCatching {
+            var hasNextPage = true
+            var page = 1
+            val tempMap = mutableMapOf<String, HeanCmsTitle>()
+
+            while (hasNextPage) {
+                val response = client.newCall(allTitlesRequest(page)).execute()
+                val json = response.body.string()
+
+                if (json.startsWith("{")) {
+                    val result = json.parseAs<HeanCmsQuerySearchDto>()
+                    tempMap.putAll(parseAllTitles(result.data))
+                    hasNextPage = result.meta?.hasNextPage ?: false
+                    page++
+                } else {
+                    val result = json.parseAs<List<HeanCmsSeriesDto>>()
+                    tempMap.putAll(parseAllTitles(result))
+                    hasNextPage = false
+                }
+            }
+
+            tempMap.toMap()
+        }
+
+        seriesSlugMap = result.getOrNull()
+    }
+
+    protected open fun allTitlesRequest(page: Int): Request {
+        if (useNewQueryEndpoint) {
+            val url = "$apiUrl/query".toHttpUrl().newBuilder()
+                .addQueryParameter("series_type", "Comic")
+                .addQueryParameter("page", page.toString())
+                .addQueryParameter("perPage", PER_PAGE_MANGA_TITLES.toString())
+
+            return GET(url.build(), headers)
+        }
+
+        val payloadObj = HeanCmsQuerySearchPayloadDto(
+            page = page,
+            order = "desc",
+            orderBy = "total_views",
+            type = "Comic",
+        )
+
+        val payload = json.encodeToString(payloadObj).toRequestBody(JSON_MEDIA_TYPE)
+
+        val apiHeaders = headersBuilder()
+            .add("Accept", ACCEPT_JSON)
+            .add("Content-Type", payload.contentType().toString())
+            .build()
+
+        return POST("$apiUrl/series/querysearch", apiHeaders, payload)
+    }
+
+    protected open fun parseAllTitles(result: List<HeanCmsSeriesDto>): Map<String, HeanCmsTitle> {
+        return result
+            .filter { it.type == "Comic" }
+            .associateBy(
+                keySelector = { it.slug.replace(TIMESTAMP_REGEX, "") },
+                valueTransform = {
+                    HeanCmsTitle(
+                        slug = it.slug,
+                        thumbnailFileName = it.thumbnail,
+                        status = it.status?.toStatus() ?: SManga.UNKNOWN,
+                    )
+                },
+            )
+    }
+
+    /**
+     * Used to store the current slugs for sources that change it periodically and for the
+     * search that doesn't return the thumbnail URLs.
+     */
+    data class HeanCmsTitle(val slug: String, val thumbnailFileName: String, val status: Int)
+
+    private fun String.toPermSlugIfNeeded(): String {
+        return if (fetchAllTitles) {
+            this.replace(TIMESTAMP_REGEX, "")
+        } else {
+            this
+        }
+    }
+
     protected open fun getStatusList(): List<Status> = listOf(
         Status(intl.statusAll, "All"),
         Status(intl.statusOngoing, "Ongoing"),
@@ -312,6 +522,8 @@ abstract class HeanCms(
 
         val TIMESTAMP_REGEX = """-\d{13}$""".toRegex()
 
+        private const val PER_PAGE_MANGA_TITLES = 10000
+
         const val SEARCH_PREFIX = "slug:"
     }
 }
diff --git a/multisrc/src/main/java/eu/kanade/tachiyomi/multisrc/heancms/HeanCmsDto.kt b/multisrc/src/main/java/eu/kanade/tachiyomi/multisrc/heancms/HeanCmsDto.kt
index 24e296a33..6e765ad44 100644
--- a/multisrc/src/main/java/eu/kanade/tachiyomi/multisrc/heancms/HeanCmsDto.kt
+++ b/multisrc/src/main/java/eu/kanade/tachiyomi/multisrc/heancms/HeanCmsDto.kt
@@ -35,10 +35,15 @@ data class HeanCmsSearchDto(
     fun toSManga(
         apiUrl: String,
         coverPath: String,
+        slugMap: Map<String, HeanCms.HeanCmsTitle>,
+        fetchAllTiles: Boolean,
     ): SManga = SManga.create().apply {
+        val slugOnly = slug.toPermSlugIfNeeded(fetchAllTiles)
+        val thumbnailFileName = slugMap[slugOnly]?.thumbnailFileName
         title = this@HeanCmsSearchDto.title
         thumbnail_url = thumbnail?.toAbsoluteThumbnailUrl(apiUrl, coverPath)
-        url = "/series/$slug"
+            ?: thumbnailFileName?.toAbsoluteThumbnailUrl(apiUrl, coverPath)
+        url = "/series/$slugOnly"
     }
 }
 
@@ -61,8 +66,10 @@ data class HeanCmsSeriesDto(
     fun toSManga(
         apiUrl: String,
         coverPath: String,
+        fetchAllTiles: Boolean,
     ): SManga = SManga.create().apply {
         val descriptionBody = this@HeanCmsSeriesDto.description?.let(Jsoup::parseBodyFragment)
+        val slugOnly = slug.toPermSlugIfNeeded(fetchAllTiles)
 
         title = this@HeanCmsSeriesDto.title
         author = this@HeanCmsSeriesDto.author?.trim()
@@ -76,7 +83,7 @@ data class HeanCmsSeriesDto(
         thumbnail_url = thumbnail.ifEmpty { null }
             ?.toAbsoluteThumbnailUrl(apiUrl, coverPath)
         status = this@HeanCmsSeriesDto.status?.toStatus() ?: SManga.UNKNOWN
-        url = "/series/$slug"
+        url = "/series/$slugOnly"
     }
 }
 
@@ -98,7 +105,6 @@ data class HeanCmsChapterDto(
     @SerialName("created_at") val createdAt: String,
     val price: Int? = null,
 ) {
-
     fun toSChapter(seriesSlug: String, dateFormat: SimpleDateFormat): SChapter = SChapter.create().apply {
         name = this@HeanCmsChapterDto.name.trim()
         date_upload = runCatching { dateFormat.parse(createdAt)?.time }
@@ -134,6 +140,14 @@ private fun String.toAbsoluteThumbnailUrl(apiUrl: String, coverPath: String): St
     return if (startsWith("https://")) this else "$apiUrl/$coverPath$this"
 }
 
+private fun String.toPermSlugIfNeeded(fetchAllTitles: Boolean): String {
+    return if (fetchAllTitles) {
+        this.replace(HeanCms.TIMESTAMP_REGEX, "")
+    } else {
+        this
+    }
+}
+
 fun String.toStatus(): Int = when (this) {
     "Ongoing" -> SManga.ONGOING
     "Hiatus" -> SManga.ON_HIATUS
diff --git a/multisrc/src/main/java/eu/kanade/tachiyomi/multisrc/heancms/HeanCmsGenerator.kt b/multisrc/src/main/java/eu/kanade/tachiyomi/multisrc/heancms/HeanCmsGenerator.kt
index 956515456..57c75cd24 100644
--- a/multisrc/src/main/java/eu/kanade/tachiyomi/multisrc/heancms/HeanCmsGenerator.kt
+++ b/multisrc/src/main/java/eu/kanade/tachiyomi/multisrc/heancms/HeanCmsGenerator.kt
@@ -9,7 +9,7 @@ class HeanCmsGenerator : ThemeSourceGenerator {
 
     override val themeClass = "HeanCms"
 
-    override val baseVersionCode: Int = 16
+    override val baseVersionCode: Int = 17
 
     override val sources = listOf(
         SingleLang("Glorious Scan", "https://gloriousscan.com", "pt-BR", overrideVersionCode = 17),