diff --git a/src/main/java/ctbrec/recorder/server/HttpServer.java b/src/main/java/ctbrec/recorder/server/HttpServer.java
index 00537280..5767b72e 100644
--- a/src/main/java/ctbrec/recorder/server/HttpServer.java
+++ b/src/main/java/ctbrec/recorder/server/HttpServer.java
@@ -20,6 +20,7 @@ import ctbrec.Config;
 import ctbrec.recorder.LocalRecorder;
 import ctbrec.recorder.Recorder;
 import ctbrec.sites.Site;
+import ctbrec.sites.bonga.BongaCams;
 import ctbrec.sites.cam4.Cam4;
 import ctbrec.sites.camsoda.Camsoda;
 import ctbrec.sites.chaturbate.Chaturbate;
@@ -66,6 +67,7 @@ public class HttpServer {
         sites.add(new MyFreeCams());
         sites.add(new Camsoda());
         sites.add(new Cam4());
+        sites.add(new BongaCams());
     }
 
     private void addShutdownHook() {
diff --git a/src/main/java/ctbrec/sites/bonga/BongaCams.java b/src/main/java/ctbrec/sites/bonga/BongaCams.java
new file mode 100644
index 00000000..61e46340
--- /dev/null
+++ b/src/main/java/ctbrec/sites/bonga/BongaCams.java
@@ -0,0 +1,123 @@
+package ctbrec.sites.bonga;
+
+import java.io.IOException;
+
+import ctbrec.Model;
+import ctbrec.io.HttpClient;
+import ctbrec.recorder.Recorder;
+import ctbrec.sites.AbstractSite;
+import ctbrec.ui.TabProvider;
+import javafx.scene.Node;
+
+public class BongaCams extends AbstractSite {
+
+    public static final String BASE_URL = "https://bongacams.com";
+
+    private BongaCamsHttpClient httpClient;
+
+    private Recorder recorder;
+
+    @Override
+    public String getName() {
+        return "BongaCams";
+    }
+
+    @Override
+    public String getBaseUrl() {
+        return BASE_URL;
+    }
+
+    @Override
+    public String getAffiliateLink() {
+        return BASE_URL;
+    }
+
+    @Override
+    public void setRecorder(Recorder recorder) {
+        this.recorder = recorder;
+    }
+
+    @Override
+    public TabProvider getTabProvider() {
+        return new BongaCamsTabProvider(recorder, this);
+    }
+
+    @Override
+    public Model createModel(String name) {
+        BongaCamsModel model = new BongaCamsModel();
+        model.setName(name);
+        model.setUrl(BASE_URL + '/' + name);
+        model.setDescription("");
+        model.setSite(this);
+        return model;
+    }
+
+    @Override
+    public Integer getTokenBalance() throws IOException {
+        // TODO Auto-generated method stub
+        return 0;
+    }
+
+    @Override
+    public String getBuyTokensLink() {
+        // TODO Auto-generated method stub
+        return getBaseUrl();
+    }
+
+    @Override
+    public void login() throws IOException {
+        // TODO Auto-generated method stub
+
+    }
+
+    @Override
+    public HttpClient getHttpClient() {
+        if(httpClient == null) {
+            httpClient = new BongaCamsHttpClient();
+        }
+        return httpClient;
+    }
+
+    @Override
+    public void init() throws IOException {
+        // TODO Auto-generated method stub
+
+    }
+
+    @Override
+    public void shutdown() {
+        // TODO Auto-generated method stub
+
+    }
+
+    @Override
+    public boolean supportsTips() {
+        // TODO Auto-generated method stub
+        return false;
+    }
+
+    @Override
+    public boolean supportsFollow() {
+        // TODO Auto-generated method stub
+        return false;
+    }
+
+    @Override
+    public boolean isSiteForModel(Model m) {
+        // TODO Auto-generated method stub
+        return false;
+    }
+
+    @Override
+    public Node getConfigurationGui() {
+        // TODO Auto-generated method stub
+        return null;
+    }
+
+    @Override
+    public boolean credentialsAvailable() {
+        // TODO Auto-generated method stub
+        return false;
+    }
+
+}
diff --git a/src/main/java/ctbrec/sites/bonga/BongaCamsHttpClient.java b/src/main/java/ctbrec/sites/bonga/BongaCamsHttpClient.java
new file mode 100644
index 00000000..a7de6816
--- /dev/null
+++ b/src/main/java/ctbrec/sites/bonga/BongaCamsHttpClient.java
@@ -0,0 +1,15 @@
+package ctbrec.sites.bonga;
+
+import java.io.IOException;
+
+import ctbrec.io.HttpClient;
+
+public class BongaCamsHttpClient extends HttpClient {
+
+    @Override
+    public boolean login() throws IOException {
+        // TODO Auto-generated method stub
+        return false;
+    }
+
+}
diff --git a/src/main/java/ctbrec/sites/bonga/BongaCamsModel.java b/src/main/java/ctbrec/sites/bonga/BongaCamsModel.java
new file mode 100644
index 00000000..dba742fe
--- /dev/null
+++ b/src/main/java/ctbrec/sites/bonga/BongaCamsModel.java
@@ -0,0 +1,193 @@
+package ctbrec.sites.bonga;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import java.util.concurrent.ExecutionException;
+
+import org.json.JSONObject;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.iheartradio.m3u8.Encoding;
+import com.iheartradio.m3u8.Format;
+import com.iheartradio.m3u8.ParseException;
+import com.iheartradio.m3u8.PlaylistException;
+import com.iheartradio.m3u8.PlaylistParser;
+import com.iheartradio.m3u8.data.MasterPlaylist;
+import com.iheartradio.m3u8.data.Playlist;
+import com.iheartradio.m3u8.data.PlaylistData;
+import com.iheartradio.m3u8.data.StreamInfo;
+
+import ctbrec.AbstractModel;
+import ctbrec.recorder.download.StreamSource;
+import ctbrec.sites.Site;
+import okhttp3.FormBody;
+import okhttp3.Request;
+import okhttp3.RequestBody;
+import okhttp3.Response;
+
+public class BongaCamsModel extends AbstractModel {
+
+    private static final transient Logger LOG = LoggerFactory.getLogger(BongaCamsModel.class);
+
+    private BongaCams site;
+    private int userId;
+    private String onlineState = "n/a";
+    private boolean online = false;
+    private List<StreamSource> streamSources = new ArrayList<>();
+    private int[] resolution;
+
+    @Override
+    public boolean isOnline(boolean ignoreCache) throws IOException, ExecutionException, InterruptedException {
+        return online;
+    }
+
+    public void setOnline(boolean online) {
+        this.online = online;
+    }
+
+    @Override
+    public String getOnlineState(boolean failFast) throws IOException, ExecutionException {
+        return onlineState;
+    }
+
+    public void setOnlineState(String onlineState) {
+        this.onlineState = onlineState;
+    }
+
+    @Override
+    public List<StreamSource> getStreamSources() throws IOException, ExecutionException, ParseException, PlaylistException {
+        String streamUrl = getStreamUrl();
+        if (streamUrl == null) {
+            return Collections.emptyList();
+        }
+        Request req = new Request.Builder().url(streamUrl).build();
+        Response response = site.getHttpClient().execute(req);
+        try {
+            InputStream inputStream = response.body().byteStream();
+            PlaylistParser parser = new PlaylistParser(inputStream, Format.EXT_M3U, Encoding.UTF_8);
+            Playlist playlist = parser.parse();
+            MasterPlaylist master = playlist.getMasterPlaylist();
+            for (PlaylistData playlistData : master.getPlaylists()) {
+
+                StreamSource streamsource = new StreamSource();
+                streamsource.mediaPlaylistUrl = streamUrl.replace("playlist.m3u8", playlistData.getUri());
+                if (playlistData.hasStreamInfo()) {
+                    StreamInfo info = playlistData.getStreamInfo();
+                    streamsource.bandwidth = info.getBandwidth();
+                    streamsource.width = info.hasResolution() ? info.getResolution().width : 0;
+                    streamsource.height = info.hasResolution() ? info.getResolution().height : 0;
+                } else {
+                    streamsource.bandwidth = 0;
+                    streamsource.width = 0;
+                    streamsource.height = 0;
+                }
+                streamSources.add(streamsource);
+            }
+        } finally {
+            response.close();
+        }
+        return streamSources;
+    }
+
+    private String getStreamUrl() throws IOException {
+        String url = BongaCams.BASE_URL + "/tools/amf.php";
+        RequestBody body = new FormBody.Builder()
+                .add("method", "getRoomData")
+                .add("args[]", getName())
+                .add("args[]", "false")
+                .build();
+        Request request = new Request.Builder()
+                .url(url)
+                .addHeader("User-Agent", "Mozilla/5.0 (Android 9.0; Mobile; rv:61.0) Gecko/61.0 Firefox/61.0")
+                .addHeader("Accept", "application/json, text/javascript, */*")
+                .addHeader("Accept-Language", "en")
+                .addHeader("Referer", BongaCams.BASE_URL)
+                .addHeader("X-Requested-With", "XMLHttpRequest")
+                .post(body)
+                .build();
+        try(Response response = site.getHttpClient().execute(request)) {
+            if(response.isSuccessful()) {
+                JSONObject json = new JSONObject(response.body().string());
+                if(json.optString("status").equals("success")) {
+                    JSONObject localData = json.getJSONObject("localData");
+                    String server = localData.getString("videoServerUrl");
+                    return "https:" + server + "/hls/stream_" + getName() + "/playlist.m3u8";
+                } else {
+                    throw new IOException("Request was not successful: " + json.toString(2));
+                }
+            } else {
+                throw new IOException(response.code() + " " + response.message());
+            }
+        }
+    }
+
+    @Override
+    public void invalidateCacheEntries() {
+        // TODO Auto-generated method stub
+
+    }
+
+    @Override
+    public void receiveTip(int tokens) throws IOException {
+        // TODO Auto-generated method stub
+
+    }
+
+    @Override
+    public int[] getStreamResolution(boolean failFast) throws ExecutionException {
+        if(resolution == null) {
+            if(failFast) {
+                return new int[2];
+            }
+            try {
+                List<StreamSource> streamSources = getStreamSources();
+                Collections.sort(streamSources);
+                StreamSource best = streamSources.get(streamSources.size()-1);
+                resolution = new int[] {best.width, best.height};
+            } catch (ExecutionException | IOException | ParseException | PlaylistException e) {
+                LOG.error("Couldn't determine stream resolution", e);
+            }
+            return resolution;
+        } else {
+            return resolution;
+        }
+    }
+
+    @Override
+    public boolean follow() throws IOException {
+        // TODO Auto-generated method stub
+        return false;
+    }
+
+    @Override
+    public boolean unfollow() throws IOException {
+        // TODO Auto-generated method stub
+        return false;
+    }
+
+    @Override
+    public void setSite(Site site) {
+        if(site instanceof BongaCams) {
+            this.site = (BongaCams) site;
+        } else {
+            throw new IllegalArgumentException("Site has to be an instance of BongaCams");
+        }
+    }
+
+    @Override
+    public Site getSite() {
+        return site;
+    }
+
+    public int getUserId() {
+        return userId;
+    }
+
+    public void setUserId(int userId) {
+        this.userId = userId;
+    }
+}
diff --git a/src/main/java/ctbrec/sites/bonga/BongaCamsTabProvider.java b/src/main/java/ctbrec/sites/bonga/BongaCamsTabProvider.java
new file mode 100644
index 00000000..ebe42de3
--- /dev/null
+++ b/src/main/java/ctbrec/sites/bonga/BongaCamsTabProvider.java
@@ -0,0 +1,39 @@
+package ctbrec.sites.bonga;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import ctbrec.recorder.Recorder;
+import ctbrec.ui.PaginatedScheduledService;
+import ctbrec.ui.TabProvider;
+import ctbrec.ui.ThumbOverviewTab;
+import javafx.scene.Scene;
+import javafx.scene.control.Tab;
+
+public class BongaCamsTabProvider extends TabProvider {
+
+    private BongaCams bongaCams;
+    private Recorder recorder;
+
+    public BongaCamsTabProvider(Recorder recorder, BongaCams bongaCams) {
+        this.recorder = recorder;
+        this.bongaCams = bongaCams;
+    }
+
+    @Override
+    public List<Tab> getTabs(Scene scene) {
+        List<Tab> tabs = new ArrayList<>();
+
+        BongaCamsUpdateService updateService = new BongaCamsUpdateService(bongaCams);
+        tabs.add(createTab("Online", updateService));
+
+        return tabs;
+    }
+
+    private Tab createTab(String title, PaginatedScheduledService updateService) {
+        ThumbOverviewTab tab = new ThumbOverviewTab(title, updateService, bongaCams);
+        tab.setRecorder(recorder);
+        return tab;
+    }
+
+}
diff --git a/src/main/java/ctbrec/sites/bonga/BongaCamsUpdateService.java b/src/main/java/ctbrec/sites/bonga/BongaCamsUpdateService.java
new file mode 100644
index 00000000..4d2164ba
--- /dev/null
+++ b/src/main/java/ctbrec/sites/bonga/BongaCamsUpdateService.java
@@ -0,0 +1,71 @@
+package ctbrec.sites.bonga;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.List;
+
+import org.json.JSONArray;
+import org.json.JSONObject;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import ctbrec.Model;
+import ctbrec.ui.PaginatedScheduledService;
+import javafx.concurrent.Task;
+import okhttp3.Request;
+import okhttp3.Response;
+
+public class BongaCamsUpdateService extends PaginatedScheduledService {
+
+    private static final transient Logger LOG = LoggerFactory.getLogger(BongaCamsUpdateService.class);
+
+    private BongaCams bongaCams;
+
+    public BongaCamsUpdateService(BongaCams bongaCams) {
+        this.bongaCams = bongaCams;
+    }
+
+    @Override
+    protected Task<List<Model>> createTask() {
+        return new Task<List<Model>>() {
+            @Override
+            public List<Model> call() throws IOException {
+                String url = BongaCams.BASE_URL + "/tools/listing_v3.php?livetab=female&online_only=true&is_mobile=true&offset=" + ((page-1) * 50);
+                LOG.debug("Fetching page {}", url);
+                Request request = new Request.Builder()
+                        .url(url)
+                        .addHeader("User-Agent", "Mozilla/5.0 (Android 9.0; Mobile; rv:61.0) Gecko/61.0 Firefox/61.0")
+                        .addHeader("Accept", "application/json, text/javascript, */*")
+                        .addHeader("Accept-Language", "en")
+                        .addHeader("Referer", bongaCams.getBaseUrl())
+                        .addHeader("X-Requested-With", "XMLHttpRequest")
+                        .build();
+                Response response = bongaCams.getHttpClient().execute(request);
+                if (response.isSuccessful()) {
+                    String content = response.body().string();
+                    response.close();
+                    List<Model> models = new ArrayList<>();
+                    JSONObject json = new JSONObject(content);
+                    if(json.optString("status").equals("success")) {
+                        JSONArray _models = json.getJSONArray("models");
+                        for (int i = 0; i < _models.length(); i++) {
+                            JSONObject m = _models.getJSONObject(i);
+                            String name = m.getString("username");
+                            BongaCamsModel model = (BongaCamsModel) bongaCams.createModel(name);
+                            model.setUserId(m.getInt("user_id"));
+                            model.setOnlineState(m.getString("room"));
+                            model.setOnline(m.optBoolean("online") && !m.optBoolean("is_away"));
+                            model.setPreview("https:" + m.getString("thumb_image"));
+                            models.add(model);
+                        }
+                    }
+                    return models;
+                } else {
+                    int code = response.code();
+                    response.close();
+                    throw new IOException("HTTP status " + code);
+                }
+            }
+        };
+    }
+}
diff --git a/src/main/java/ctbrec/ui/CamrecApplication.java b/src/main/java/ctbrec/ui/CamrecApplication.java
index 90be7e79..3fdf6466 100644
--- a/src/main/java/ctbrec/ui/CamrecApplication.java
+++ b/src/main/java/ctbrec/ui/CamrecApplication.java
@@ -27,6 +27,7 @@ import ctbrec.recorder.LocalRecorder;
 import ctbrec.recorder.Recorder;
 import ctbrec.recorder.RemoteRecorder;
 import ctbrec.sites.Site;
+import ctbrec.sites.bonga.BongaCams;
 import ctbrec.sites.cam4.Cam4;
 import ctbrec.sites.camsoda.Camsoda;
 import ctbrec.sites.chaturbate.Chaturbate;
@@ -64,6 +65,7 @@ public class CamrecApplication extends Application {
         sites.add(new MyFreeCams());
         sites.add(new Camsoda());
         sites.add(new Cam4());
+        sites.add(new BongaCams());
         loadConfig();
         createHttpClient();
         bus = new AsyncEventBus(Executors.newSingleThreadExecutor());