diff --git a/lib-multisrc/madara/build.gradle.kts b/lib-multisrc/madara/build.gradle.kts
index 8255bf3e7..d96dd889d 100644
--- a/lib-multisrc/madara/build.gradle.kts
+++ b/lib-multisrc/madara/build.gradle.kts
@@ -2,7 +2,7 @@ plugins {
     id("lib-multisrc")
 }
 
-baseVersionCode = 39
+baseVersionCode = 40
 
 dependencies {
     api(project(":lib:cryptoaes"))
diff --git a/lib-multisrc/madara/src/eu/kanade/tachiyomi/multisrc/madara/Madara.kt b/lib-multisrc/madara/src/eu/kanade/tachiyomi/multisrc/madara/Madara.kt
index 074512f36..00a019ce5 100644
--- a/lib-multisrc/madara/src/eu/kanade/tachiyomi/multisrc/madara/Madara.kt
+++ b/lib-multisrc/madara/src/eu/kanade/tachiyomi/multisrc/madara/Madara.kt
@@ -82,7 +82,12 @@ abstract class Madara(
     /**
      * Automatically fetched genres from the source to be used in the filters.
      */
-    private var genresList: List<Genre> = emptyList()
+    protected open var genresList: List<Genre> = emptyList()
+
+    /**
+     * Whether genres have been fetched
+     */
+    private var genresFetched: Boolean = false
 
     /**
      * Inner variable to control how much tries the genres request was called.
@@ -237,11 +242,14 @@ abstract class Madara(
 
     override fun fetchSearchManga(page: Int, query: String, filters: FilterList): Observable<MangasPage> {
         if (query.startsWith(URL_SEARCH_PREFIX)) {
-            val mangaUrl = "/$mangaSubString/${query.substringAfter(URL_SEARCH_PREFIX)}/"
-            return client.newCall(GET("$baseUrl$mangaUrl", headers))
+            val mangaUrl = baseUrl.toHttpUrl().newBuilder().apply {
+                addPathSegment(mangaSubString)
+                addPathSegment(query.substringAfter(URL_SEARCH_PREFIX))
+            }.build()
+            return client.newCall(GET(mangaUrl, headers))
                 .asObservableSuccess().map { response ->
                     val manga = mangaDetailsParse(response).apply {
-                        url = mangaUrl
+                        setUrlWithoutDomain(mangaUrl.toString())
                     }
 
                     MangasPage(listOf(manga), false)
@@ -1069,10 +1077,17 @@ abstract class Madara(
      * Fetch the genres from the source to be used in the filters.
      */
     protected fun fetchGenres() {
-        if (fetchGenres && fetchGenresAttempts < 3 && genresList.isEmpty()) {
+        if (fetchGenres && fetchGenresAttempts < 3 && !genresFetched) {
             try {
-                genresList = client.newCall(genresRequest()).execute()
+                client.newCall(genresRequest()).execute()
                     .use { parseGenres(it.asJsoup()) }
+                    .also {
+                        genresFetched = true
+                    }
+                    .takeIf { it.isNotEmpty() }
+                    ?.also {
+                        genresList = it
+                    }
             } catch (_: Exception) {
             } finally {
                 fetchGenresAttempts++
diff --git a/src/en/gourmetscans/src/eu/kanade/tachiyomi/extension/en/gourmetscans/GourmetScans.kt b/src/en/gourmetscans/src/eu/kanade/tachiyomi/extension/en/gourmetscans/GourmetScans.kt
index 657a736f0..84239f371 100644
--- a/src/en/gourmetscans/src/eu/kanade/tachiyomi/extension/en/gourmetscans/GourmetScans.kt
+++ b/src/en/gourmetscans/src/eu/kanade/tachiyomi/extension/en/gourmetscans/GourmetScans.kt
@@ -61,24 +61,22 @@ class GourmetScans : Madara(
     override fun genresRequest(): Request = GET("$baseUrl/$mangaSubString", headers)
 
     override fun parseGenres(document: Document): List<Genre> {
-        genresList = document.select("div.row.genres ul li a")
+        return document.select("div.row.genres ul li a")
             .orEmpty()
             .map { li ->
-                Pair(
+                Genre(
                     li.text(),
                     li.attr("href").split("/").last { it.isNotBlank() },
                 )
             }
-
-        return emptyList()
     }
 
-    private var genresList: List<Pair<String, String>> = emptyList()
-
-    class GenreFilter(vals: List<Pair<String, String>>) :
-        UriPartFilter("Genre", vals.toTypedArray())
+    class GenreFilter(vals: List<Genre>) :
+        UriPartFilter("Genre", vals.map { Pair(it.name, it.id) }.toTypedArray())
 
     override fun getFilterList(): FilterList {
+        launchIO { fetchGenres() }
+
         val filters = buildList(4) {
             add(YearFilter(intl["year_filter_title"]))
             add(
@@ -93,7 +91,7 @@ class GourmetScans : Madara(
             if (genresList.isEmpty()) {
                 add(Filter.Header(intl["genre_missing_warning"]))
             } else {
-                add(GenreFilter(listOf(Pair("<select>", "")) + genresList))
+                add(GenreFilter(listOf(Genre("<select>", "")) + genresList))
             }
         }
 
diff --git a/src/en/manga18fx/src/eu/kanade/tachiyomi/extension/en/manga18fx/Manga18fx.kt b/src/en/manga18fx/src/eu/kanade/tachiyomi/extension/en/manga18fx/Manga18fx.kt
index 87c54b9ea..3e8112f91 100644
--- a/src/en/manga18fx/src/eu/kanade/tachiyomi/extension/en/manga18fx/Manga18fx.kt
+++ b/src/en/manga18fx/src/eu/kanade/tachiyomi/extension/en/manga18fx/Manga18fx.kt
@@ -68,7 +68,7 @@ class Manga18fx : Madara(
         if (query.isEmpty()) {
             filters.forEach { filter ->
                 if (filter is GenreFilter) {
-                    return GET(filter.vals[filter.state].second, headers)
+                    return GET(filter.vals[filter.state].id, headers)
                 }
             }
             return latestUpdatesRequest(page)
@@ -94,23 +94,22 @@ class Manga18fx : Madara(
 
     override fun chapterDateSelector() = "span.chapter-time"
 
-    class GenreFilter(val vals: List<Pair<String, String>>) :
-        Filter.Select<String>("Genre", vals.map { it.first }.toTypedArray())
+    class GenreFilter(val vals: List<Genre>) :
+        Filter.Select<String>("Genre", vals.map { it.name }.toTypedArray())
 
     private fun loadGenres(document: Document) {
         genresList = document.select(".header-bottom li a").map {
             val href = it.attr("href")
             val url = if (href.startsWith("http")) href else "$baseUrl/$href"
 
-            Pair(it.text(), url)
+            Genre(it.text(), url)
         }
     }
 
-    private var genresList: List<Pair<String, String>> = emptyList()
-    private var hardCodedTypes: List<Pair<String, String>> = listOf(
-        Pair("Manhwa", "$baseUrl/manga-genre/manhwa"),
-        Pair("Manhua", "$baseUrl/manga-genre/manhua"),
-        Pair("Raw", "$baseUrl/manga-genre/raw"),
+    private var hardCodedTypes: List<Genre> = listOf(
+        Genre("Manhwa", "$baseUrl/manga-genre/manhwa"),
+        Genre("Manhua", "$baseUrl/manga-genre/manhua"),
+        Genre("Raw", "$baseUrl/manga-genre/raw"),
     )
 
     override fun getFilterList(): FilterList {
diff --git a/src/en/manhwahentaime/src/eu/kanade/tachiyomi/extension/en/manhwahentaime/ManhwahentaiMe.kt b/src/en/manhwahentaime/src/eu/kanade/tachiyomi/extension/en/manhwahentaime/ManhwahentaiMe.kt
index 8d5408062..0e712d028 100644
--- a/src/en/manhwahentaime/src/eu/kanade/tachiyomi/extension/en/manhwahentaime/ManhwahentaiMe.kt
+++ b/src/en/manhwahentaime/src/eu/kanade/tachiyomi/extension/en/manhwahentaime/ManhwahentaiMe.kt
@@ -104,35 +104,22 @@ class ManhwahentaiMe : Madara("Manhwahentai.me", "https://manhwahentai.me", "en"
         intl["order_by_filter_new"] to "new-manga",
     )
 
-    private var genresList: List<Pair<String, String>> = emptyList()
-    private var fetchGenresAttempts: Int = 0
-
-    private fun fetchGenresMe() {
-        if (fetchGenres && fetchGenresAttempts < 3 && genresList.isEmpty()) {
-            try {
-                genresList = client.newCall(genresRequest()).execute()
-                    .use { parseGenresMe(it.asJsoup()) }
-            } catch (_: Exception) {
-            } finally {
-                fetchGenresAttempts++
-            }
-        }
-    }
-
-    private fun parseGenresMe(document: Document): List<Pair<String, String>> {
+    override fun parseGenres(document: Document): List<Genre> {
         return document.selectFirst("div.genres")
             ?.select("a")
             .orEmpty()
             .map { a ->
-                a.ownText() to
-                    a.attr("href").substringBeforeLast("/").substringAfterLast("/")
+                Genre(
+                    a.ownText(),
+                    a.attr("href").substringBeforeLast("/").substringAfterLast("/"),
+                )
             }.let {
-                listOf(("All" to "all")) + it
+                listOf(Genre("All", "all")) + it
             }
     }
 
     override fun getFilterList(): FilterList {
-        launchIO { fetchGenresMe() }
+        launchIO { fetchGenres() }
 
         val filters = mutableListOf(
             Filter.Header("All filters except the orderby filter are incompatible with each other"),
@@ -145,17 +132,16 @@ class ManhwahentaiMe : Madara("Manhwahentai.me", "https://manhwahentai.me", "en"
             ),
         )
 
-        if (genresList.isNotEmpty()) {
-            filters += listOf(
+        filters += if (genresList.isNotEmpty()) {
+            listOf(
                 Filter.Separator(),
-                Filter.Header(intl["genre_filter_header"]),
                 GenreConditionFilter(
                     title = intl["genre_filter_title"],
-                    options = genresList,
+                    options = genresList.map { it.name to it.id },
                 ),
             )
-        } else if (fetchGenres) {
-            filters += listOf(
+        } else {
+            listOf(
                 Filter.Separator(),
                 Filter.Header(intl["genre_missing_warning"]),
             )
diff --git a/src/en/manycomic/src/eu/kanade/tachiyomi/extension/en/manycomic/ManyComic.kt b/src/en/manycomic/src/eu/kanade/tachiyomi/extension/en/manycomic/ManyComic.kt
index b6dd40d20..e66168486 100644
--- a/src/en/manycomic/src/eu/kanade/tachiyomi/extension/en/manycomic/ManyComic.kt
+++ b/src/en/manycomic/src/eu/kanade/tachiyomi/extension/en/manycomic/ManyComic.kt
@@ -5,7 +5,6 @@ import eu.kanade.tachiyomi.network.GET
 import eu.kanade.tachiyomi.network.POST
 import eu.kanade.tachiyomi.source.model.Filter
 import eu.kanade.tachiyomi.source.model.FilterList
-import eu.kanade.tachiyomi.util.asJsoup
 import okhttp3.FormBody
 import okhttp3.HttpUrl.Companion.toHttpUrl
 import okhttp3.Request
@@ -67,7 +66,7 @@ class ManyComic : Madara("ManyComic", "https://manycomic.com", "en") {
     override fun searchMangaSelector() = popularMangaSelector()
 
     override fun getFilterList(): FilterList {
-        launchIO { fetchGenres_() }
+        launchIO { fetchGenres() }
 
         val filters: MutableList<Filter<out Any>> = mutableListOf(
             OrderByFilter(
@@ -77,18 +76,18 @@ class ManyComic : Madara("ManyComic", "https://manycomic.com", "en") {
             ),
         )
 
-        if (genresList.isNotEmpty()) {
-            filters += listOf(
+        filters += if (genresList.isNotEmpty()) {
+            listOf(
                 Filter.Separator(),
                 Filter.Header("Genre filter is ignored when searching by title"),
                 GenreFilter(
                     title = intl["genre_filter_title"],
-                    options = genresList,
+                    options = listOf(Genre("<All>", "")) + genresList,
                     state = 0,
                 ),
             )
-        } else if (fetchGenres) {
-            filters += listOf(
+        } else {
+            listOf(
                 Filter.Separator(),
                 Filter.Header(intl["genre_missing_warning"]),
             )
@@ -106,22 +105,6 @@ class ManyComic : Madara("ManyComic", "https://manycomic.com", "en") {
         intl["order_by_filter_new"] to "new-manga",
     )
 
-    private var genresList: List<Genre> = emptyList()
-    private var fetchGenresAttempts: Int = 0
-
-    private fun fetchGenres_() {
-        if (fetchGenres && fetchGenresAttempts < 3 && genresList.isEmpty()) {
-            try {
-                genresList = listOf(Genre("<All>", "")) +
-                    client.newCall(genresRequest()).execute()
-                        .use { parseGenres(it.asJsoup()) }
-            } catch (_: Exception) {
-            } finally {
-                fetchGenresAttempts++
-            }
-        }
-    }
-
     private class GenreFilter(title: String, options: List<Genre>, state: Int = 0) :
         UriPartFilter(title, options.map { Pair(it.name, it.id) }.toTypedArray(), state)
 }
diff --git a/src/en/manytoon/src/eu/kanade/tachiyomi/extension/en/manytoon/ManyToon.kt b/src/en/manytoon/src/eu/kanade/tachiyomi/extension/en/manytoon/ManyToon.kt
index bc6876ed9..4a56371c2 100644
--- a/src/en/manytoon/src/eu/kanade/tachiyomi/extension/en/manytoon/ManyToon.kt
+++ b/src/en/manytoon/src/eu/kanade/tachiyomi/extension/en/manytoon/ManyToon.kt
@@ -5,7 +5,6 @@ import eu.kanade.tachiyomi.network.GET
 import eu.kanade.tachiyomi.network.POST
 import eu.kanade.tachiyomi.source.model.Filter
 import eu.kanade.tachiyomi.source.model.FilterList
-import eu.kanade.tachiyomi.util.asJsoup
 import okhttp3.FormBody
 import okhttp3.HttpUrl.Companion.toHttpUrl
 import okhttp3.Request
@@ -94,35 +93,22 @@ class ManyToon : Madara("ManyToon", "https://manytoon.com", "en") {
         intl["order_by_filter_new"] to "new-manga",
     )
 
-    private var genresList: List<Pair<String, String>> = emptyList()
-    private var fetchGenresAttempts: Int = 0
-
-    private fun fetchGenresMe() {
-        if (fetchGenres && fetchGenresAttempts < 3 && genresList.isEmpty()) {
-            try {
-                genresList = client.newCall(genresRequest()).execute()
-                    .use { parseGenresMe(it.asJsoup()) }
-            } catch (_: Exception) {
-            } finally {
-                fetchGenresAttempts++
-            }
-        }
-    }
-
-    private fun parseGenresMe(document: Document): List<Pair<String, String>> {
+    override fun parseGenres(document: Document): List<Genre> {
         return document.selectFirst("div.genres")
             ?.select("a")
             .orEmpty()
             .map { a ->
-                a.ownText() to
-                    a.attr("href").substringBeforeLast("/").substringAfterLast("/")
+                Genre(
+                    a.ownText(),
+                    a.attr("href").substringBeforeLast("/").substringAfterLast("/"),
+                )
             }.let {
-                listOf(("All" to "all")) + it
+                listOf(Genre("All", "all")) + it
             }
     }
 
     override fun getFilterList(): FilterList {
-        launchIO { fetchGenresMe() }
+        launchIO { fetchGenres() }
 
         val filters = mutableListOf(
             Filter.Header("All filters except the orderby filter are incompatible with each other"),
@@ -135,17 +121,16 @@ class ManyToon : Madara("ManyToon", "https://manytoon.com", "en") {
             ),
         )
 
-        if (genresList.isNotEmpty()) {
-            filters += listOf(
+        filters += if (genresList.isNotEmpty()) {
+            listOf(
                 Filter.Separator(),
-                Filter.Header(intl["genre_filter_header"]),
                 GenreConditionFilter(
                     title = intl["genre_filter_title"],
-                    options = genresList,
+                    options = genresList.map { it.name to it.id },
                 ),
             )
-        } else if (fetchGenres) {
-            filters += listOf(
+        } else {
+            listOf(
                 Filter.Separator(),
                 Filter.Header(intl["genre_missing_warning"]),
             )
diff --git a/src/es/leermanga/src/eu/kanade/tachiyomi/extension/es/leermanga/LeerManga.kt b/src/es/leermanga/src/eu/kanade/tachiyomi/extension/es/leermanga/LeerManga.kt
index 355108198..3fe896036 100644
--- a/src/es/leermanga/src/eu/kanade/tachiyomi/extension/es/leermanga/LeerManga.kt
+++ b/src/es/leermanga/src/eu/kanade/tachiyomi/extension/es/leermanga/LeerManga.kt
@@ -80,19 +80,16 @@ class LeerManga : Madara(
 
     // =============================== Filters ===============================
 
-    private var genresList: List<Genre> = emptyList()
-
     override fun getFilterList(): FilterList {
         val filters = mutableListOf<Filter<*>>()
         if (genresList.isNotEmpty()) {
             filters += listOf(
-                Filter.Header(intl["genre_filter_header"]),
                 GenreGroup(
                     displayName = intl["genre_filter_title"],
                     genres = genresList,
                 ),
             )
-        } else if (fetchGenres) {
+        } else {
             filters += Filter.Header(intl["genre_missing_warning"])
         }
         return FilterList(filters)
diff --git a/src/id/mgkomik/src/eu/kanade/tachiyomi/extension/id/mgkomik/MGKomik.kt b/src/id/mgkomik/src/eu/kanade/tachiyomi/extension/id/mgkomik/MGKomik.kt
index 48923d001..4606c640d 100644
--- a/src/id/mgkomik/src/eu/kanade/tachiyomi/extension/id/mgkomik/MGKomik.kt
+++ b/src/id/mgkomik/src/eu/kanade/tachiyomi/extension/id/mgkomik/MGKomik.kt
@@ -5,7 +5,6 @@ import eu.kanade.tachiyomi.network.GET
 import eu.kanade.tachiyomi.network.interceptor.rateLimit
 import eu.kanade.tachiyomi.source.model.Filter
 import eu.kanade.tachiyomi.source.model.FilterList
-import eu.kanade.tachiyomi.util.asJsoup
 import okhttp3.Request
 import org.jsoup.nodes.Document
 import java.text.SimpleDateFormat
@@ -84,26 +83,21 @@ class MGKomik : Madara(
 
     // ================================ Filters ================================
 
-    private var genresList: List<Genre> = emptyList()
-
-    override val fetchGenres = false
-
     override fun getFilterList(): FilterList {
-        launchIO { fetchGenresOption() }
+        launchIO { fetchGenres() }
 
         val filters = super.getFilterList().list.toMutableList()
 
-        if (genresList.isNotEmpty()) {
-            filters += listOf(
+        filters += if (genresList.isNotEmpty()) {
+            listOf(
                 Filter.Separator(),
-                Filter.Header(intl["genre_filter_header"]),
                 GenreContentFilter(
                     title = intl["genre_filter_title"],
                     options = genresList.map { it.name to it.id },
                 ),
             )
-        } else if (fetchGenres) {
-            filters += listOf(
+        } else {
+            listOf(
                 Filter.Separator(),
                 Filter.Header(intl["genre_missing_warning"]),
             )
@@ -119,20 +113,6 @@ class MGKomik : Madara(
 
     override fun genresRequest() = GET("$baseUrl/$mangaSubString", headers)
 
-    private var fetchGenresAttempts: Int = 0
-
-    fun fetchGenresOption() {
-        if (fetchGenresAttempts < 3 && genresList.isEmpty()) {
-            try {
-                genresList = client.newCall(genresRequest()).execute()
-                    .use { parseGenres(it.asJsoup()) }
-            } catch (_: Exception) {
-            } finally {
-                fetchGenresAttempts++
-            }
-        }
-    }
-
     override fun parseGenres(document: Document): List<Genre> {
         val genres = mutableListOf<Genre>()
         genres += Genre("All", "")
diff --git a/src/id/pojokmanga/src/eu/kanade/tachiyomi/extension/id/pojokmanga/PojokManga.kt b/src/id/pojokmanga/src/eu/kanade/tachiyomi/extension/id/pojokmanga/PojokManga.kt
index 246f09f59..02a09b47c 100644
--- a/src/id/pojokmanga/src/eu/kanade/tachiyomi/extension/id/pojokmanga/PojokManga.kt
+++ b/src/id/pojokmanga/src/eu/kanade/tachiyomi/extension/id/pojokmanga/PojokManga.kt
@@ -83,7 +83,7 @@ class PojokManga : Madara("Pojok Manga", "https://pojokmanga.info", "id", Simple
 
     override val mangaDetailsSelectorTag = "#toNotBeUsed"
 
-    protected class ProjectFilter : UriPartFilter(
+    private class ProjectFilter : UriPartFilter(
         "Filter Project",
         arrayOf(
             Pair("Show all manga", ""),