diff --git a/src/all/nhentai/build.gradle b/src/all/nhentai/build.gradle
index df27a7181..48060d37e 100644
--- a/src/all/nhentai/build.gradle
+++ b/src/all/nhentai/build.gradle
@@ -5,7 +5,7 @@ ext {
     appName = 'Tachiyomi: NHentai'
     pkgNameSuffix = 'all.nhentai'
     extClass = '.NHFactory'
-    extVersionCode = 24
+    extVersionCode = 25
     libVersion = '1.2'
 }
 
diff --git a/src/all/nhentai/src/eu/kanade/tachiyomi/extension/all/nhentai/NHentai.kt b/src/all/nhentai/src/eu/kanade/tachiyomi/extension/all/nhentai/NHentai.kt
index 0e5aff7d1..627992e1b 100644
--- a/src/all/nhentai/src/eu/kanade/tachiyomi/extension/all/nhentai/NHentai.kt
+++ b/src/all/nhentai/src/eu/kanade/tachiyomi/extension/all/nhentai/NHentai.kt
@@ -152,27 +152,52 @@ open class NHentai(
 
     override fun searchMangaRequest(page: Int, query: String, filters: FilterList): Request {
         val filters = if (filters.isEmpty()) getFilterList() else filters
-
+        val advQuery = combineQuery(filters)
         val favoriteFilter = filters.findInstance<FavoriteFilter>()
+        val uploadedFilter = filters.findInstance<UploadedFilter>()
+
         if (favoriteFilter != null && favoriteFilter.state) {
             val url = HttpUrl.parse("$baseUrl/favorites")!!.newBuilder()
-                .addQueryParameter("q", query)
+                .addQueryParameter("q", "$query $advQuery")
                 .addQueryParameter("page", page.toString())
 
             return GET(url.toString(), headers)
         } else {
             val url = HttpUrl.parse("$baseUrl/search")!!.newBuilder()
-                .addQueryParameter("q", "$query +$nhLang")
+                .addQueryParameter("q", "$query +$nhLang $advQuery")
                 .addQueryParameter("page", page.toString())
 
-            filters.findInstance<SortFilter>()?.let { f ->
-                url.addQueryParameter("sort", f.values[f.state].toLowerCase())
+            if (uploadedFilter!!.state.isBlank()) {
+                filters.findInstance<SortFilter>()?.let { f ->
+                    url.addQueryParameter("sort", f.toUriPart())
+                }
             }
 
             return GET(url.toString(), headers)
         }
     }
 
+    private fun combineQuery(filters: FilterList): String {
+        val stringBuilder = StringBuilder()
+        val advSearch = filters.filterIsInstance<AdvSearchEntryFilter>().flatMap { filter ->
+            val splitState = filter.state.split(",").map(String::trim).filterNot(String::isBlank)
+            splitState.map {
+                AdvSearchEntry(filter.name, it.removePrefix("-"), it.startsWith("-"))
+            }
+        }
+
+        advSearch.forEach { entry ->
+            if (entry.exclude) stringBuilder.append("-")
+            stringBuilder.append("${entry.name}:")
+            stringBuilder.append(entry.text)
+            stringBuilder.append(" ")
+        }
+
+        return stringBuilder.toString()
+    }
+
+    data class AdvSearchEntry(val name: String, val text: String, val exclude: Boolean)
+
     private fun searchMangaByIdRequest(id: String) = GET("$baseUrl/g/$id", headers)
 
     private fun searchMangaByIdParse(response: Response, id: String): MangasPage {
@@ -241,16 +266,51 @@ open class NHentai(
     }
 
     override fun getFilterList(): FilterList = FilterList(
+        Filter.Header("Separate tags with commas (,)"),
+        Filter.Header("Prepend with dash (-) to exclude"),
+        TagFilter(),
+        CategoryFilter(),
+        GroupFilter(),
+        ArtistFilter(),
+        ParodyFilter(),
+        CharactersFilter(),
+        Filter.Header("Uploaded valid units are h, d, w, m, y."),
+        Filter.Header("example: (>20d)"),
+        UploadedFilter(),
+
+        Filter.Separator(),
         SortFilter(),
         Filter.Header("Sort is ignored if favorites only"),
         FavoriteFilter()
     )
 
+    class TagFilter : AdvSearchEntryFilter("Tags")
+    class CategoryFilter : AdvSearchEntryFilter("Categories")
+    class GroupFilter : AdvSearchEntryFilter("Groups")
+    class ArtistFilter : AdvSearchEntryFilter("Artists")
+    class ParodyFilter : AdvSearchEntryFilter("Parodies")
+    class CharactersFilter : AdvSearchEntryFilter("Characters")
+    class UploadedFilter : AdvSearchEntryFilter("Uploaded")
+    open class AdvSearchEntryFilter(name: String) : Filter.Text(name)
+
     override fun imageUrlParse(document: Document) = throw UnsupportedOperationException("Not used")
 
     private class FavoriteFilter : Filter.CheckBox("Show favorites only", false)
 
-    private class SortFilter : Filter.Select<String>("Sort", arrayOf("Popular", "Date"))
+    private class SortFilter : UriPartFilter(
+        "Sort By",
+        arrayOf(
+            Pair("Popular: All Time", "popular"),
+            Pair("Popular: Week", "popular-week"),
+            Pair("Popular: Today", "popular-today"),
+            Pair("Recent", "date")
+        )
+    )
+
+    private open class UriPartFilter(displayName: String, val vals: Array<Pair<String, String>>) :
+        Filter.Select<String>(displayName, vals.map { it.first }.toTypedArray()) {
+        fun toUriPart() = vals[state].second
+    }
 
     private inline fun <reified T> Iterable<*>.findInstance() = find { it is T } as? T