diff --git a/common-dependencies.gradle b/common-dependencies.gradle
index 0e652f81b..5fda67310 100644
--- a/common-dependencies.gradle
+++ b/common-dependencies.gradle
@@ -12,6 +12,8 @@ dependencies {
     compileOnly 'org.jsoup:jsoup:1.13.1'
     compileOnly 'com.google.code.gson:gson:2.8.6'
     compileOnly 'com.github.salomonbrys.kotson:kotson:2.5.0'
+    compileOnly 'org.jetbrains.kotlinx:kotlinx-serialization-protobuf:1.2.0'
+    compileOnly 'org.jetbrains.kotlinx:kotlinx-serialization-json:1.2.0'
 
     implementation project(":annotations")
     compileOnly project(':duktape-stub')
diff --git a/src/all/mangaplus/build.gradle b/src/all/mangaplus/build.gradle
index bdf041b4a..983b0c894 100644
--- a/src/all/mangaplus/build.gradle
+++ b/src/all/mangaplus/build.gradle
@@ -6,12 +6,8 @@ ext {
     extName = 'MANGA Plus by SHUEISHA'
     pkgNameSuffix = 'all.mangaplus'
     extClass = '.MangaPlusFactory'
-    extVersionCode = 18
+    extVersionCode = 19
     libVersion = '1.2'
 }
 
-dependencies {
-    implementation 'org.jetbrains.kotlinx:kotlinx-serialization-protobuf:1.2.0'
-}
-
 apply from: "$rootDir/common.gradle"
diff --git a/src/all/mangaplus/src/eu/kanade/tachiyomi/extension/all/mangaplus/MangaPlusFactory.kt b/src/all/mangaplus/src/eu/kanade/tachiyomi/extension/all/mangaplus/MangaPlusFactory.kt
index f775e6198..bb0f6b26b 100644
--- a/src/all/mangaplus/src/eu/kanade/tachiyomi/extension/all/mangaplus/MangaPlusFactory.kt
+++ b/src/all/mangaplus/src/eu/kanade/tachiyomi/extension/all/mangaplus/MangaPlusFactory.kt
@@ -18,4 +18,3 @@ class MangaPlusIndonesian : MangaPlus("id", "eng", Language.INDONESIAN)
 class MangaPlusPortuguese : MangaPlus("pt-BR", "eng", Language.PORTUGUESE_BR)
 class MangaPlusSpanish : MangaPlus("es", "esp", Language.SPANISH)
 class MangaPlusThai : MangaPlus("th", "eng", Language.THAI)
-
diff --git a/src/pt/bruttal/build.gradle b/src/pt/bruttal/build.gradle
index ab3eacca6..79def1be9 100644
--- a/src/pt/bruttal/build.gradle
+++ b/src/pt/bruttal/build.gradle
@@ -1,15 +1,15 @@
 apply plugin: 'com.android.application'
 apply plugin: 'kotlin-android'
+apply plugin: 'kotlinx-serialization'
 
 ext {
     extName = 'Bruttal'
     pkgNameSuffix = 'pt.bruttal'
     extClass = '.Bruttal'
-    extVersionCode = 2
+    extVersionCode = 3
     libVersion = '1.2'
 }
 
-
 dependencies {
     implementation project(':lib-ratelimit')
 }
diff --git a/src/pt/bruttal/src/eu/kanade/tachiyomi/extension/pt/bruttal/Bruttal.kt b/src/pt/bruttal/src/eu/kanade/tachiyomi/extension/pt/bruttal/Bruttal.kt
index e4b33647d..ce552f316 100644
--- a/src/pt/bruttal/src/eu/kanade/tachiyomi/extension/pt/bruttal/Bruttal.kt
+++ b/src/pt/bruttal/src/eu/kanade/tachiyomi/extension/pt/bruttal/Bruttal.kt
@@ -1,12 +1,5 @@
 package eu.kanade.tachiyomi.extension.pt.bruttal
 
-import com.github.salomonbrys.kotson.array
-import com.github.salomonbrys.kotson.get
-import com.github.salomonbrys.kotson.obj
-import com.github.salomonbrys.kotson.string
-import com.google.gson.JsonElement
-import com.google.gson.JsonObject
-import com.google.gson.JsonParser
 import eu.kanade.tachiyomi.lib.ratelimit.RateLimitInterceptor
 import eu.kanade.tachiyomi.network.GET
 import eu.kanade.tachiyomi.network.asObservableSuccess
@@ -16,11 +9,14 @@ 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 kotlinx.serialization.decodeFromString
+import kotlinx.serialization.json.Json
 import okhttp3.Headers
 import okhttp3.OkHttpClient
 import okhttp3.Request
 import okhttp3.Response
 import rx.Observable
+import uy.kohesive.injekt.injectLazy
 import java.util.concurrent.TimeUnit
 
 class Bruttal : HttpSource() {
@@ -41,6 +37,8 @@ class Bruttal : HttpSource() {
         .add("Referer", "$baseUrl/bruttal/")
         .add("User-Agent", USER_AGENT)
 
+    private val json: Json by injectLazy()
+
     override fun popularMangaRequest(page: Int): Request {
         val newHeaders = headersBuilder()
             .add("Accept", "application/json, text/plain, */*")
@@ -50,19 +48,17 @@ class Bruttal : HttpSource() {
     }
 
     override fun popularMangaParse(response: Response): MangasPage {
-        val json = response.asJson().obj
+        val homeDto = json.decodeFromString<BruttalHomeDto>(response.body!!.string())
 
-        val titles = json["list"].array.map { jsonEl ->
-            popularMangaFromObject(jsonEl.obj)
-        }
+        val titles = homeDto.list.map(::popularMangaFromObject)
 
         return MangasPage(titles, false)
     }
 
-    private fun popularMangaFromObject(obj: JsonObject): SManga = SManga.create().apply {
-        title = obj["title"].string
-        thumbnail_url = "$baseUrl/bruttal/" + obj["image_mobile"].string.removePrefix("./")
-        url = "/bruttal" + obj["url"].string
+    private fun popularMangaFromObject(comicbook: BruttalComicBookDto): SManga = SManga.create().apply {
+        title = comicbook.title
+        thumbnail_url = "$baseUrl/bruttal/" + comicbook.imageMobile.removePrefix("./")
+        url = "/bruttal" + comicbook.url
     }
 
     override fun fetchSearchManga(page: Int, query: String, filters: FilterList): Observable<MangasPage> {
@@ -96,20 +92,20 @@ class Bruttal : HttpSource() {
     }
 
     override fun mangaDetailsParse(response: Response): SManga {
-        val json = response.asJson().array
+        val comicBooks = json.decodeFromString<List<BruttalComicBookDto>>(response.body!!.string())
 
-        val titleUrl = response.request.header("Referer")!!.substringAfter("/bruttal")
-        val titleObj = json.first { it.obj["url"].string == titleUrl }.obj
-        val soonText = titleObj["soon_text"].string
+        val comicBookUrl = response.request.header("Referer")!!
+            .substringAfter("/bruttal")
+        val currentComicBook = comicBooks.first { it.url == comicBookUrl }
 
         return SManga.create().apply {
-            title = titleObj["title"].string
-            thumbnail_url = "$baseUrl/bruttal/" + titleObj["image_mobile"].string.removePrefix("./")
-            description = titleObj["synopsis"].string +
-                (if (soonText.isEmpty()) "" else "\n\n$soonText")
-            artist = titleObj["illustrator"].string
-            author = titleObj["author"].string
-            genre = titleObj["keywords"].string.replace("; ", ", ")
+            title = currentComicBook.title
+            thumbnail_url = "$baseUrl/bruttal/" + currentComicBook.imageMobile.removePrefix("./")
+            description = currentComicBook.synopsis +
+                (if (currentComicBook.soonText.isEmpty()) "" else "\n\n${currentComicBook.soonText}")
+            artist = currentComicBook.illustrator
+            author = currentComicBook.author
+            genre = currentComicBook.keywords.replace("; ", ", ")
             status = SManga.ONGOING
         }
     }
@@ -118,21 +114,24 @@ class Bruttal : HttpSource() {
     override fun chapterListRequest(manga: SManga): Request = mangaDetailsApiRequest(manga)
 
     override fun chapterListParse(response: Response): List<SChapter> {
-        val json = response.asJson().array
+        val comicBooks = json.decodeFromString<List<BruttalComicBookDto>>(response.body!!.string())
 
-        val titleUrl = response.request.header("Referer")!!.substringAfter("/bruttal")
-        val title = json.first { it.obj["url"].string == titleUrl }.obj
+        val comicBookUrl = response.request.header("Referer")!!
+            .substringAfter("/bruttal")
+        val currentComicBook = comicBooks.first { it.url == comicBookUrl }
 
-        return title["seasons"].array
-            .flatMap { it.obj["chapters"].array }
-            .map { jsonEl -> chapterFromObject(jsonEl.obj) }
+        return currentComicBook.seasons
+            .flatMap { it.chapters }
+            .map(::chapterFromObject)
             .reversed()
     }
 
-    private fun chapterFromObject(obj: JsonObject): SChapter = SChapter.create().apply {
-        name = obj["title"].string
-        chapter_number = obj["share_title"].string.removePrefix("Capítulo ").toFloatOrNull() ?: -1f
-        url = "/bruttal" + obj["url"].string
+    private fun chapterFromObject(chapter: BruttalChapterDto): SChapter = SChapter.create().apply {
+        name = chapter.title
+        chapter_number = chapter.shareTitle
+            .removePrefix("Capítulo ")
+            .toFloatOrNull() ?: -1f
+        url = "/bruttal" + chapter.url
     }
 
     override fun pageListRequest(chapter: SChapter): Request {
@@ -145,22 +144,28 @@ class Bruttal : HttpSource() {
     }
 
     override fun pageListParse(response: Response): List<Page> {
-        val json = response.asJson().array
+        val comicBooks = json.decodeFromString<List<BruttalComicBookDto>>(response.body!!.string())
 
         val chapterUrl = response.request.header("Referer")!!
-        val titleSlug = chapterUrl.substringAfter("bruttal/").substringBefore("/")
-        val season = chapterUrl.substringAfter("temporada-").substringBefore("/").toInt()
-        val chapter = chapterUrl.substringAfter("capitulo-")
+        val comicBookSlug = chapterUrl
+            .substringAfter("bruttal/")
+            .substringBefore("/")
+        val seasonNumber = chapterUrl
+            .substringAfter("temporada-")
+            .substringBefore("/")
+        val chapterNumber = chapterUrl.substringAfter("capitulo-")
 
-        val titleObj = json.first { it.obj["url"].string == "/$titleSlug" }.obj
-        val seasonObj = titleObj["seasons"].array[season - 1].obj
-        val chapterObj = seasonObj["chapters"].array.first {
-            it.obj["alias"].string.substringAfter("-") == chapter
+        val currentComicBook = comicBooks.first { it.url == "/$comicBookSlug" }
+        val currentSeason = currentComicBook.seasons.first {
+            it.alias.substringAfter("-") == seasonNumber
+        }
+        val currentChapter = currentSeason.chapters.first {
+            it.alias.substringAfter("-") == chapterNumber
         }
 
-        return chapterObj["images"].array
-            .mapIndexed { i, jsonEl ->
-                val imageUrl = "$baseUrl/bruttal/" + jsonEl.obj["image"].string.removePrefix("./")
+        return currentChapter.images
+            .mapIndexed { i, bruttalImage ->
+                val imageUrl = "$baseUrl/bruttal/" + bruttalImage.image.removePrefix("./")
                 Page(i, chapterUrl, imageUrl)
             }
     }
@@ -184,10 +189,8 @@ class Bruttal : HttpSource() {
 
     override fun latestUpdatesParse(response: Response): MangasPage = throw UnsupportedOperationException("Not used")
 
-    private fun Response.asJson(): JsonElement = JsonParser.parseString(body!!.string())
-
     companion object {
         private const val USER_AGENT = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) " +
-            "AppleWebKit/537.36 (KHTML, like Gecko) Chrome/89.0.4389.128 Safari/537.36"
+            "AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.77 Safari/537.36"
     }
 }
diff --git a/src/pt/bruttal/src/eu/kanade/tachiyomi/extension/pt/bruttal/BruttalDto.kt b/src/pt/bruttal/src/eu/kanade/tachiyomi/extension/pt/bruttal/BruttalDto.kt
new file mode 100644
index 000000000..c1088eb2d
--- /dev/null
+++ b/src/pt/bruttal/src/eu/kanade/tachiyomi/extension/pt/bruttal/BruttalDto.kt
@@ -0,0 +1,42 @@
+package eu.kanade.tachiyomi.extension.pt.bruttal
+
+import kotlinx.serialization.SerialName
+import kotlinx.serialization.Serializable
+
+@Serializable
+data class BruttalHomeDto(
+    val list: List<BruttalComicBookDto> = emptyList()
+)
+
+@Serializable
+data class BruttalComicBookDto(
+    val author: String,
+    val illustrator: String,
+    @SerialName("image_mobile") val imageMobile: String,
+    val keywords: String,
+    val seasons: List<BruttalSeasonDto> = emptyList(),
+    @SerialName("soon_text") val soonText: String = "",
+    val synopsis: String,
+    val title: String,
+    val url: String
+)
+
+@Serializable
+data class BruttalSeasonDto(
+    val alias: String,
+    val chapters: List<BruttalChapterDto> = emptyList()
+)
+
+@Serializable
+data class BruttalChapterDto(
+    val alias: String,
+    val images: List<BruttalImageDto> = emptyList(),
+    @SerialName("share_title") val shareTitle: String,
+    val title: String,
+    val url: String
+)
+
+@Serializable
+data class BruttalImageDto(
+    val image: String
+)
diff --git a/src/pt/hipercool/build.gradle b/src/pt/hipercool/build.gradle
index 8acd7b957..f01503d28 100644
--- a/src/pt/hipercool/build.gradle
+++ b/src/pt/hipercool/build.gradle
@@ -1,11 +1,12 @@
 apply plugin: 'com.android.application'
 apply plugin: 'kotlin-android'
+apply plugin: 'kotlinx-serialization'
 
 ext {
     extName = 'HipercooL'
     pkgNameSuffix = 'pt.hipercool'
     extClass = '.Hipercool'
-    extVersionCode = 6
+    extVersionCode = 7
     libVersion = '1.2'
     containsNsfw = true
 }
diff --git a/src/pt/hipercool/src/eu/kanade/tachiyomi/extension/pt/hipercool/Hipercool.kt b/src/pt/hipercool/src/eu/kanade/tachiyomi/extension/pt/hipercool/Hipercool.kt
index 8858f5e51..56ed3e822 100644
--- a/src/pt/hipercool/src/eu/kanade/tachiyomi/extension/pt/hipercool/Hipercool.kt
+++ b/src/pt/hipercool/src/eu/kanade/tachiyomi/extension/pt/hipercool/Hipercool.kt
@@ -1,17 +1,7 @@
 package eu.kanade.tachiyomi.extension.pt.hipercool
 
-import com.github.salomonbrys.kotson.array
-import com.github.salomonbrys.kotson.get
-import com.github.salomonbrys.kotson.int
-import com.github.salomonbrys.kotson.jsonObject
-import com.github.salomonbrys.kotson.obj
-import com.github.salomonbrys.kotson.string
-import com.google.gson.JsonArray
-import com.google.gson.JsonElement
-import com.google.gson.JsonObject
-import com.google.gson.JsonParser
 import eu.kanade.tachiyomi.annotations.Nsfw
-import eu.kanade.tachiyomi.lib.ratelimit.RateLimitInterceptor
+import eu.kanade.tachiyomi.lib.ratelimit.SpecificHostRateLimitInterceptor
 import eu.kanade.tachiyomi.network.GET
 import eu.kanade.tachiyomi.network.POST
 import eu.kanade.tachiyomi.network.asObservableSuccess
@@ -21,7 +11,13 @@ 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 kotlinx.serialization.decodeFromString
+import kotlinx.serialization.json.Json
+import kotlinx.serialization.json.JsonPrimitive
+import kotlinx.serialization.json.buildJsonObject
+import kotlinx.serialization.json.put
 import okhttp3.Headers
+import okhttp3.HttpUrl.Companion.toHttpUrl
 import okhttp3.HttpUrl.Companion.toHttpUrlOrNull
 import okhttp3.MediaType.Companion.toMediaTypeOrNull
 import okhttp3.OkHttpClient
@@ -29,10 +25,10 @@ import okhttp3.Request
 import okhttp3.RequestBody.Companion.toRequestBody
 import okhttp3.Response
 import rx.Observable
+import uy.kohesive.injekt.injectLazy
 import java.text.ParseException
 import java.text.SimpleDateFormat
 import java.util.Locale
-import java.util.concurrent.TimeUnit
 
 @Nsfw
 class Hipercool : HttpSource() {
@@ -49,7 +45,8 @@ class Hipercool : HttpSource() {
     override val supportsLatest = true
 
     override val client: OkHttpClient = network.cloudflareClient.newBuilder()
-        .addInterceptor(RateLimitInterceptor(1, 1, TimeUnit.SECONDS))
+        .addInterceptor(SpecificHostRateLimitInterceptor(baseUrl.toHttpUrl(), 1))
+        .addInterceptor(SpecificHostRateLimitInterceptor(STATIC_URL.toHttpUrl(), 2))
         .build()
 
     override fun headersBuilder(): Headers.Builder = Headers.Builder()
@@ -57,31 +54,27 @@ class Hipercool : HttpSource() {
         .add("Referer", baseUrl)
         .add("X-Requested-With", "XMLHttpRequest")
 
-    private fun genericMangaListParse(response: Response): MangasPage {
-        val result = response.asJson().array
+    private val json: Json by injectLazy()
 
-        if (result.size() == 0)
+    private fun genericMangaListParse(response: Response): MangasPage {
+        val chapters = json.decodeFromString<List<HipercoolChapterDto>>(response.body!!.string())
+
+        if (chapters.isEmpty())
             return MangasPage(emptyList(), false)
 
-        val mangaList = result
-            .map { genericMangaFromObject(it.obj) }
+        val mangaList = chapters
+            .map(::genericMangaFromObject)
             .distinctBy { it.title }
 
-        val hasNextPage = result.size() == DEFAULT_COUNT
+        val hasNextPage = chapters.size == DEFAULT_COUNT
 
         return MangasPage(mangaList, hasNextPage)
     }
 
-    private fun genericMangaFromObject(obj: JsonObject): SManga {
-        val book = obj["_book"].obj
-        val bookSlug = book["slug"].string
-        val bookRevision = book["revision"]?.int ?: 1
-
-        return SManga.create().apply {
-            title = book["title"].string
-            thumbnail_url = bookSlug.toThumbnailUrl(bookRevision)
-            url = "/books/$bookSlug"
-        }
+    private fun genericMangaFromObject(chapter: HipercoolChapterDto): SManga = SManga.create().apply {
+        title = chapter.book!!.title
+        thumbnail_url = chapter.book.slug.toThumbnailUrl(chapter.book.revision)
+        url = "/books/" + chapter.book.slug
     }
 
     // The source does not have popular mangas, so use latest instead.
@@ -100,12 +93,12 @@ class Hipercool : HttpSource() {
         val mediaType = "application/json; charset=utf-8".toMediaTypeOrNull()
 
         // Create json body.
-        val json = jsonObject(
-            "start" to (page - 1) * DEFAULT_COUNT,
-            "count" to DEFAULT_COUNT,
-            "text" to query,
-            "type" to "text"
-        )
+        val json = buildJsonObject {
+            put("start", (page - 1) * DEFAULT_COUNT)
+            put("content", DEFAULT_COUNT)
+            put("text", query)
+            put("type", "text")
+        }
 
         val body = json.toString().toRequestBody(mediaType)
 
@@ -130,27 +123,27 @@ class Hipercool : HttpSource() {
     }
 
     override fun mangaDetailsParse(response: Response): SManga {
-        val result = response.asJson().obj
+        val book = json.decodeFromString<HipercoolBookDto>(response.body!!.string())
 
-        val artists = result["tags"].array
-            .filter { it["label"].string == "Artista" }
-            .flatMap { it["values"].array }
-            .joinToString("; ") { it["label"].string }
+        val artists = book.tags
+            .filter { it.label == "Artista" }
+            .flatMap { it.values }
+            .joinToString("; ") { it.label }
 
-        val authors = result["tags"].array
-            .filter { it["label"].string == "Autor" }
-            .flatMap { it["values"].array }
-            .joinToString("; ") { it["label"].string }
+        val authors = book.tags
+            .filter { it.label == "Autor" }
+            .flatMap { it.values }
+            .joinToString("; ") { it.label }
 
-        val tags = result["tags"].array
-            .filter { it["label"].string == "Tags" }
-            .flatMap { it["values"].array }
-            .joinToString(", ") { it["label"].string }
+        val tags = book.tags
+            .filter { it.label == "Tags" }
+            .flatMap { it.values }
+            .joinToString { it.label }
 
         return SManga.create().apply {
-            title = result["title"].string
-            thumbnail_url = result["slug"].string.toThumbnailUrl(result["revision"].int)
-            description = result["synopsis"]?.string ?: ""
+            title = book.title
+            thumbnail_url = book.slug.toThumbnailUrl(book.revision)
+            description = book.synopsis.orEmpty()
             artist = artists
             author = authors
             genre = tags
@@ -161,31 +154,31 @@ class Hipercool : HttpSource() {
     override fun chapterListRequest(manga: SManga): Request = mangaDetailsApiRequest(manga)
 
     override fun chapterListParse(response: Response): List<SChapter> {
-        val result = response.asJson().obj
+        val book = json.decodeFromString<HipercoolBookDto>(response.body!!.string())
 
-        if (!result["chapters"]!!.isJsonArray)
+        if (book.chapters is JsonPrimitive)
             return emptyList()
 
-        return result["chapters"].array
-            .map { chapterListItemParse(result, it.obj) }
+        return json.decodeFromString<List<HipercoolChapterDto>>(book.chapters.toString())
+            .map { chapterListItemParse(book, it) }
             .reversed()
     }
 
-    private fun chapterListItemParse(book: JsonObject, obj: JsonObject): SChapter = SChapter.create().apply {
-        name = obj["title"].string
-        chapter_number = obj["title"].string.toFloatOrNull() ?: -1f
-        // The property is written wrong.
-        date_upload = DATE_FORMATTER.tryParseTime(obj["publishied_at"].string)
+    private fun chapterListItemParse(book: HipercoolBookDto, chapter: HipercoolChapterDto): SChapter =
+        SChapter.create().apply {
+            name = "Cap. " + chapter.title
+            chapter_number = chapter.title.toFloatOrNull() ?: -1f
+            date_upload = chapter.publishedAt.toDate()
 
-        val fullUrl = "$baseUrl/books".toHttpUrlOrNull()!!.newBuilder()
-            .addPathSegment(book["slug"].string)
-            .addPathSegment(obj["slug"].string)
-            .addQueryParameter("images", obj["images"].int.toString())
-            .addQueryParameter("revision", book["revision"].int.toString())
-            .toString()
+            val fullUrl = "$baseUrl/books".toHttpUrlOrNull()!!.newBuilder()
+                .addPathSegment(book.slug)
+                .addPathSegment(chapter.slug)
+                .addQueryParameter("images", chapter.images.toString())
+                .addQueryParameter("revision", book.revision.toString())
+                .toString()
 
-        setUrlWithoutDomain(fullUrl)
-    }
+            setUrlWithoutDomain(fullUrl)
+        }
 
     override fun fetchPageList(chapter: SChapter): Observable<List<Page>> {
         val chapterUrl = (baseUrl + chapter.url).toHttpUrlOrNull()!!
@@ -228,9 +221,9 @@ class Hipercool : HttpSource() {
         return GET(page.imageUrl!!, newHeaders)
     }
 
-    private fun SimpleDateFormat.tryParseTime(date: String): Long {
+    private fun String.toDate(): Long {
         return try {
-            parse(date.substringBefore("T"))?.time ?: 0L
+            DATE_FORMATTER.parse(substringBefore("T"))?.time ?: 0L
         } catch (e: ParseException) {
             0L
         }
@@ -243,13 +236,11 @@ class Hipercool : HttpSource() {
             .addQueryParameter("revision", revision.toString())
             .toString()
 
-    private fun Response.asJson(): JsonElement = JsonParser.parseString(body!!.string())
-
     companion object {
         private const val STATIC_URL = "https://static.hiper.cool"
 
         private const val USER_AGENT = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) " +
-            "AppleWebKit/537.36 (KHTML, like Gecko) Chrome/89.0.4389.128 Safari/537.36"
+            "AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.77 Safari/537.36"
 
         private const val DEFAULT_COUNT = 40
 
diff --git a/src/pt/hipercool/src/eu/kanade/tachiyomi/extension/pt/hipercool/HipercoolDto.kt b/src/pt/hipercool/src/eu/kanade/tachiyomi/extension/pt/hipercool/HipercoolDto.kt
new file mode 100644
index 000000000..31ebd048e
--- /dev/null
+++ b/src/pt/hipercool/src/eu/kanade/tachiyomi/extension/pt/hipercool/HipercoolDto.kt
@@ -0,0 +1,30 @@
+package eu.kanade.tachiyomi.extension.pt.hipercool
+
+import kotlinx.serialization.SerialName
+import kotlinx.serialization.Serializable
+import kotlinx.serialization.json.JsonElement
+
+@Serializable
+data class HipercoolBookDto(
+    val chapters: JsonElement,
+    val revision: Int = 1,
+    val slug: String,
+    val synopsis: String? = null,
+    val tags: List<HipercoolTagDto> = emptyList(),
+    val title: String
+)
+
+@Serializable
+data class HipercoolTagDto(
+    val label: String,
+    val values: List<HipercoolTagDto> = emptyList()
+)
+
+@Serializable
+data class HipercoolChapterDto(
+    @SerialName("_book") val book: HipercoolBookDto? = null,
+    val images: Int = 0,
+    @SerialName("publishied_at") val publishedAt: String,
+    val slug: String,
+    val title: String
+)
diff --git a/src/zh/dmzj/build.gradle b/src/zh/dmzj/build.gradle
index 54748c9f9..b662c7aba 100644
--- a/src/zh/dmzj/build.gradle
+++ b/src/zh/dmzj/build.gradle
@@ -6,13 +6,12 @@ ext {
     extName = 'Dmzj'
     pkgNameSuffix = 'zh.dmzj'
     extClass = '.Dmzj'
-    extVersionCode = 17
+    extVersionCode = 18
     libVersion = '1.2'
 }
 
 dependencies {
     implementation project(':lib-ratelimit')
-    implementation 'org.jetbrains.kotlinx:kotlinx-serialization-protobuf:1.2.0'
 }
 
 apply from: "$rootDir/common.gradle"