diff --git a/lib/streamsb-extractor/build.gradle.kts b/lib/streamsb-extractor/build.gradle.kts
new file mode 100644
index 000000000..81f195c93
--- /dev/null
+++ b/lib/streamsb-extractor/build.gradle.kts
@@ -0,0 +1,25 @@
+plugins {
+ id("com.android.library")
+ kotlin("android")
+}
+
+android {
+ compileSdk = AndroidConfig.compileSdk
+
+ defaultConfig {
+ minSdk = AndroidConfig.minSdk
+ targetSdk = AndroidConfig.targetSdk
+ }
+}
+
+repositories {
+ mavenCentral()
+}
+
+dependencies {
+ compileOnly(libs.kotlin.stdlib)
+ compileOnly(libs.kotlin.json)
+ compileOnly(libs.okhttp)
+ compileOnly(libs.aniyomi.lib)
+}
+// BUMPS: 0
\ No newline at end of file
diff --git a/lib/streamsb-extractor/src/main/AndroidManifest.xml b/lib/streamsb-extractor/src/main/AndroidManifest.xml
new file mode 100644
index 000000000..b95c8ebfd
--- /dev/null
+++ b/lib/streamsb-extractor/src/main/AndroidManifest.xml
@@ -0,0 +1,2 @@
+
diff --git a/lib/streamsb-extractor/src/main/java/eu/kanade/tachiyomi/lib/streamsbextractor/StreamSBExtractor.kt b/lib/streamsb-extractor/src/main/java/eu/kanade/tachiyomi/lib/streamsbextractor/StreamSBExtractor.kt
new file mode 100644
index 000000000..0e105897a
--- /dev/null
+++ b/lib/streamsb-extractor/src/main/java/eu/kanade/tachiyomi/lib/streamsbextractor/StreamSBExtractor.kt
@@ -0,0 +1,76 @@
+package eu.kanade.tachiyomi.lib.streamsbextractor
+
+import eu.kanade.tachiyomi.animesource.model.Video
+import eu.kanade.tachiyomi.network.GET
+import kotlinx.serialization.decodeFromString
+import kotlinx.serialization.json.Json
+import kotlinx.serialization.json.JsonObject
+import kotlinx.serialization.json.jsonObject
+import okhttp3.Headers
+import okhttp3.OkHttpClient
+
+class StreamSBExtractor(private val client: OkHttpClient) {
+
+ protected fun bytesToHex(bytes: ByteArray): String {
+ val hexArray = "0123456789ABCDEF".toCharArray()
+ val hexChars = CharArray(bytes.size * 2)
+ for (j in bytes.indices) {
+ val v = bytes[j].toInt() and 0xFF
+
+ hexChars[j * 2] = hexArray[v ushr 4]
+ hexChars[j * 2 + 1] = hexArray[v and 0x0F]
+ }
+ return String(hexChars)
+ }
+
+ // animension, asianload and dramacool uses "common = false"
+ private fun fixUrl(url: String, common: Boolean): String {
+ val sbUrl = url.substringBefore("/e/")
+ val id = url.substringAfter("/e/")
+ .substringBefore("?")
+ .substringBefore(".html")
+ return if (common) {
+ val hexBytes = bytesToHex(id.toByteArray())
+ "$sbUrl/sources48/625a364258615242766475327c7c${hexBytes}7c7c4761574550654f7461566d347c7c73747265616d7362"
+ } else {
+ "$sbUrl/sources48/${bytesToHex("||$id||||streamsb".toByteArray())}/"
+ }
+ }
+
+ fun videosFromUrl(url: String, headers: Headers, prefix: String = "", suffix: String = "", common: Boolean = true): List