diff --git a/build/DailymotionConfig.json b/build/DailymotionConfig.json
index 179f8bbddd98cf6ea72c494f1aeab40d193c4dee..c4ffc4775635573cf84fe9b68e2a87f433312488 100644
--- a/build/DailymotionConfig.json
+++ b/build/DailymotionConfig.json
@@ -10,7 +10,7 @@
   "version": 8,
   "iconUrl": "./dailymotion.png",
   "id": "9c87e8db-e75d-48f4-afe5-2d203d4b95c5",
-  "scriptSignature": "OjAgpayE+8LfSvm+TLWCUyPzoUHzaGgSJ5bLgrYFi7nlX3jQapqgS9el5J4NBlN9/C4kSLiQ7UFNn2qcozCROPmA3F+yNxO5XISGopziFT9axARUXbY0p5AmlPoqKHWkw1LseHmRADPc/2J+BTOnbpl4QhBWBpm6ljP8SkSzTiZxTdafiQLU78yi89fYyti5329xsUzyuQztq2R32d/R0Oo3I+94hltpJnIz2MzZ/5FLGHByPjqMw8aB4F1M0DW+CzJtQ3wkMZn3/Y6vVr7Xpy0DW29pynA+tJnuurd88xWtO/aJ+s0FodDyP3OAEYuxe2OiFMTJRKIbzNzGR0i0CA==",
+  "scriptSignature": "Mkn8NphaKXrs9i0LDd0/TlNZTxZFPAErtRgGhQZiWsxCWucxmmaPuovY6dAfNc88BD+3H0R3n7mcEANFZm0AtOOV8LfezzmYOEugZgRxgYgwCTkBYlyP821WGRnPY3+SiDUA6Sv+vLwlua9jlQSixNhxOfFSWm1Ne2FwrOG2s92n1sWnQ6T6pvJxlqclq4AlsEY6HzMsGL5T0nlRlM5XDrgxxc1yI4pAObggscRPq/D7FGD3JP+D0Lls30j1W2rXhG5IYwteIFTqo2keUwWW4qxkKTqtkxBgbeEuB2W4KVJOtZkYpYDDWzDMRp/eNE/6WGN0YgxduVJTLlA9aibGfQ==",
   "scriptPublicKey": "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAwrBXc5lMXrDD4y5GLT1rnxq64nmmBcE19lvIWL/o+wTK6jebmlQss4CrpH2Pkw8cwczcA4aHQKN8+ThveJFMBxW57gf30odKrAglvvPAv9Rm9D0BZZ501jBXvz+2Rt7su/ICN97JNabjeniAxWBGgr+It3gwvgGAXmWo9FcGfPTooy+g7lErDx5S9Hy/W83b/L3Q64Ytcb4ed0zi6pfZhgpXW0ZJxiZSJRPj6JusTJclPd4OHnl6EwAL979PloyKT0EjMgMX89LAsgctJzSOJkWcQnsbcWV3SE87GyFN4/4Py+GEvvZLKv/iWhY9Dhw9G7j3hy+3QPpHd5L3KSXC4wIDAQAB",
   "packages": [
     "Http"
@@ -26,9 +26,9 @@
     "s3.dmcdn.net"
   ],
   "authentication": {
-    "loginUrl": "https://www.dailymotion.com/signin",
-    "completionUrl": "https://www.dailymotion.com/cookie/refresh_token",
+    "loginUrl": "https://www.dailymotion.com/signin?urlback=/video/x58d0gt",
     "cookiesToFind": [
+      "damd",
       "refresh_token",
       "access_token"
     ],
diff --git a/build/DailymotionScript.js b/build/DailymotionScript.js
index 531a25df6aefdfd6b765928f5d3c7a2c7bd6c453..e4829e85946a902d82b5de9d4239e21b6e96d531 100644
--- a/build/DailymotionScript.js
+++ b/build/DailymotionScript.js
@@ -1,25 +1,36 @@
 'use strict';
 
-const errorTypes = {
-    "DM001": "No video has been specified, you need to specify one.",
-    "DM002": "Content has been deleted.",
-    "DM003": "Live content is not available, i.e. it may not have started yet.",
-    "DM004": "Copyrighted content, access forbidden.",
-    "DM005": "Content rejected (this video may have been removed due to a breach of the terms of use, a copyright claim or an infringement upon third party rights).",
-    "DM006": "Publishing in progress…",
-    "DM007": "Video geo-restricted by its owner.",
-    "DM008": "Explicit content. Explicit content can be enabled using the plugin settings",
-    "DM009": "Explicit content (offsite embed)",
-    "DM010": "Private content",
-    "DM011": "An encoding error occurred",
-    "DM012": "Encoding in progress",
-    "DM013": "This video has no preset (no video stream)",
-    "DM014": "This video has not been made available on your device by its owner",
-    "DM015": "Kids host error",
-    "DM016": "Content not available on this website, it can only be watched on Dailymotion",
-    "DM019": "This content has been uploaded by an inactive channel and its access is limited"
-};
-
+const BASE_URL = "https://www.dailymotion.com";
+const BASE_URL_API = "https://graphql.api.dailymotion.com";
+const BASE_URL_API_AUTH = `${BASE_URL_API}/oauth/token`;
+const BASE_URL_VIDEO = `${BASE_URL}/video`;
+const BASE_URL_PLAYLIST = `${BASE_URL}/playlist`;
+const BASE_URL_METADATA = `${BASE_URL}/player/metadata/video`;
+const USER_AGENT = 'Mozilla/5.0 (Linux; Android 12) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.6099.230 Mobile Safari/537.36';
+// Those are used even for not logged users to make requests on the graphql api.
+//TODO: check how to get them dynamically
+const CLIENT_ID = 'f1a362d288c1b98099c7';
+const CLIENT_SECRET = 'eea605b96e01c796ff369935357eca920c5da4c5';
+const X_DM_AppInfo_Id = "com.dailymotion.neon";
+const X_DM_AppInfo_Type = "website";
+const X_DM_AppInfo_Version = "v2024-05-16T12:17:57.363Z"; //TODO check how to get this dynamically
+const X_DM_Neon_SSR = "0";
+const X_DM_Preferred_Country = ""; //TODO check how to get this from Grayjay
+const PLATFORM = "Dailymotion";
+const PLATFORM_CLAIMTYPE = 3;
+const ITEMS_PER_PAGE = 5;
+// search capabilities - upload date
+const LESS_THAN_MINUTE = "LESS_THAN_MINUTE";
+const ONE_TO_FIVE_MINUTES = "ONE_TO_FIVE_MINUTES";
+const FIVE_TO_THIRTY_MINUTES = "FIVE_TO_THIRTY_MINUTES";
+const THIRTY_TO_ONE_HOUR = "THIRTY_TO_ONE_HOUR";
+const MORE_THAN_ONE_HOUR = "MORE_THAN_ONE_HOUR";
+const DURATION_THRESHOLDS = {};
+DURATION_THRESHOLDS[LESS_THAN_MINUTE] = { min: 0, max: 60 };
+DURATION_THRESHOLDS[ONE_TO_FIVE_MINUTES] = { min: 60, max: 300 };
+DURATION_THRESHOLDS[FIVE_TO_THIRTY_MINUTES] = { min: 300, max: 1800 };
+DURATION_THRESHOLDS[THIRTY_TO_ONE_HOUR] = { min: 1800, max: 3600 };
+DURATION_THRESHOLDS[MORE_THAN_ONE_HOUR] = { min: 3600, max: null };
 const countryNamesToCode = {
     "": "",
     "Afghanistan": "AF",
@@ -293,11 +304,25 @@ const thumbnailHeight = [
     "PORTRAIT_720",
     "PORTRAIT_1080"
 ];
-const constants = {
-    creatorAvatarHeight,
-    thumbnailHeight,
-    countryNamesToCode,
-    countryNames: Object.keys(countryNamesToCode)
+const countryNames = Object.keys(countryNamesToCode);
+const errorTypes = {
+    "DM001": "No video has been specified, you need to specify one.",
+    "DM002": "Content has been deleted.",
+    "DM003": "Live content is not available, i.e. it may not have started yet.",
+    "DM004": "Copyrighted content, access forbidden.",
+    "DM005": "Content rejected (this video may have been removed due to a breach of the terms of use, a copyright claim or an infringement upon third party rights).",
+    "DM006": "Publishing in progress…",
+    "DM007": "Video geo-restricted by its owner.",
+    "DM008": "Explicit content. Explicit content can be enabled using the plugin settings",
+    "DM009": "Explicit content (offsite embed)",
+    "DM010": "Private content",
+    "DM011": "An encoding error occurred",
+    "DM012": "Encoding in progress",
+    "DM013": "This video has no preset (no video stream)",
+    "DM014": "This video has not been made available on your device by its owner",
+    "DM015": "Kids host error",
+    "DM016": "Content not available on this website, it can only be watched on Dailymotion",
+    "DM019": "This content has been uploaded by an inactive channel and its access is limited"
 };
 
 const SEARCH_SUGGESTIONS_QUERY = `
@@ -331,8 +356,9 @@ query CHANNEL_QUERY_DESKTOP(
 		avatar(height:$avatar_size) {
 			url
 		}
-		coverURL1024x: coverURL(size: "1024x")
-		coverURL1920x: coverURL(size: "1920x")
+		banner(width:LANDSCAPE_1920) {
+			url
+		}
 		tagline
 		country {
 			id
@@ -1106,6 +1132,7 @@ query PLAYLIST_VIDEO_QUERY($xid: String!, $numberOfVideos: Int = 100, $avatar_si
 		}
 		creator {
 			id
+			name
 			displayName
 			xid
 			avatar(height:$avatar_size) {
@@ -1149,6 +1176,7 @@ query PLAYLIST_VIDEO_QUERY($xid: String!, $numberOfVideos: Int = 100, $avatar_si
 					}
 					creator {
 						id
+						name
 						displayName
 						xid
 						avatar(height:$avatar_size) {
@@ -1203,7 +1231,60 @@ query SUBSCRIPTIONS_QUERY($first: Int, $page: Int) {
 	}
 }
 `;
+const GET_CHANNEL_PLAYLISTS = `
+query CHANNEL_PLAYLISTS_QUERY(
+	$channel_name: String!
+	$sort: String
+	$page: Int!
+	$first: Int!
+) {
+	channel(name: $channel_name) {
+		id
+		xid
+		channel_playlist_collections: collections(
+			sort: $sort
+			page: $page
+			first: $first
+		) {
+			pageInfo {
+				hasNextPage
+				nextPage
+			}
+			edges {
+				node {
+					id
+					xid
+					updatedAt
+					createdAt
+					name
+					description
+					thumbnailx60: thumbnailURL(size: "x60")
+					thumbnailx120: thumbnailURL(size: "x120")
+					thumbnailx240: thumbnailURL(size: "x240")
+					thumbnailx720: thumbnailURL(size: "x720")
+					stats {
+						id
+						videos {
+							id
+							total
+						}
+					}
+				}
+			}
+		}
+	}
+}
+`;
 
+let AUTHORIZATION_TOKEN_ANONYMOUS_USER = "";
+let AUTHORIZATION_TOKEN_ANONYMOUS_USER_EXPIRATION_DATE;
+let httpClientRequestToken = http.newClient(false);
+function getPreferredCountry(preferredCountryIndex) {
+    const countryName = countryNames[preferredCountryIndex];
+    const code = countryNamesToCode[countryName];
+    const preferredCountry = (code || X_DM_Preferred_Country || '').toLowerCase();
+    return preferredCountry;
+}
 const objectToUrlEncodedString = (obj) => {
     const encodedParams = [];
     for (const key in obj) {
@@ -1215,49 +1296,181 @@ const objectToUrlEncodedString = (obj) => {
     }
     return encodedParams.join('&');
 };
-var util = {
-    objectToUrlEncodedString,
-};
+function getChannelNameFromUrl(url) {
+    const channel_name = url.split('/').pop();
+    return channel_name;
+}
+function isUsernameUrl(url) {
+    var regex = new RegExp('^' + BASE_URL.replace(/\./g, '\\.') + '/[^/]+$');
+    return regex.test(url);
+}
+function getAnonymousUserTokenSingleton() {
+    // Check if the anonymous user token is available and not expired
+    if (AUTHORIZATION_TOKEN_ANONYMOUS_USER) {
+        const isTokenValid = AUTHORIZATION_TOKEN_ANONYMOUS_USER_EXPIRATION_DATE && new Date().getTime() < AUTHORIZATION_TOKEN_ANONYMOUS_USER_EXPIRATION_DATE;
+        if (isTokenValid) {
+            return AUTHORIZATION_TOKEN_ANONYMOUS_USER;
+        }
+    }
+    // Prepare the request body for obtaining a new token
+    const body = objectToUrlEncodedString({
+        client_id: CLIENT_ID,
+        client_secret: CLIENT_SECRET,
+        grant_type: 'client_credentials'
+    });
+    // Make the HTTP POST request to the authorization API
+    const res = httpClientRequestToken.POST(`${BASE_URL_API_AUTH}`, body, {
+        'User-Agent': USER_AGENT,
+        'Content-Type': 'application/x-www-form-urlencoded',
+        'Origin': BASE_URL,
+        'DNT': '1',
+        'Sec-GPC': '1',
+        'Connection': 'keep-alive',
+        'Sec-Fetch-Dest': 'empty',
+        'Sec-Fetch-Mode': 'cors',
+        'Sec-Fetch-Site': 'same-site',
+        'Priority': 'u=4',
+        'Pragma': 'no-cache',
+        'Cache-Control': 'no-cache'
+    }, false);
+    // Check if the response code indicates success
+    if (res.code !== 200) {
+        console.error('Failed to get token', res);
+        throw new ScriptException("", "Failed to get token: " + res.code + " - " + res.body);
+    }
+    // Parse the response JSON to extract the token information
+    const json = JSON.parse(res.body);
+    // Ensure the response contains the necessary token information
+    if (!json.token_type || !json.access_token) {
+        console.error('Invalid token response', res);
+        throw new ScriptException("", 'Invalid token response: ' + res.body);
+    }
+    // Store the token and its expiration date
+    AUTHORIZATION_TOKEN_ANONYMOUS_USER = `${json.token_type} ${json.access_token}`;
+    AUTHORIZATION_TOKEN_ANONYMOUS_USER_EXPIRATION_DATE = new Date().getTime() + (json.expires_in * 1000);
+    return AUTHORIZATION_TOKEN_ANONYMOUS_USER;
+}
+function executeGqlQuery(httpClient, requestOptions) {
+    const headersToAdd = requestOptions.headers || {
+        "User-Agent": USER_AGENT,
+        "Accept": "*/*",
+        // "Accept-Language": Accept_Language,
+        "Referer": BASE_URL,
+        "Origin": BASE_URL,
+        "DNT": "1",
+        "Connection": "keep-alive",
+        "Sec-Fetch-Dest": "empty",
+        "Sec-Fetch-Mode": "cors",
+        "Sec-Fetch-Site": "same-site",
+        "Pragma": "no-cache",
+        "Cache-Control": "no-cache"
+    };
+    const gql = JSON.stringify({
+        operationName: requestOptions.operationName,
+        variables: requestOptions.variables,
+        query: requestOptions.query,
+    });
+    const usePlatformAuth = requestOptions.usePlatformAuth == undefined ? false : requestOptions.usePlatformAuth;
+    const throwOnError = requestOptions.throwOnError == undefined ? true : requestOptions.throwOnError;
+    if (!usePlatformAuth) {
+        headersToAdd.Authorization = getAnonymousUserTokenSingleton();
+    }
+    const res = httpClient.POST(BASE_URL_API, gql, headersToAdd, usePlatformAuth);
+    if (!res.isOk) {
+        console.error('Failed to get token', res);
+        if (throwOnError) {
+            throw new ScriptException("Failed to get token", res);
+        }
+    }
+    const body = JSON.parse(res.body);
+    // some errors may be returned in the body with a status code 200
+    if (body.errors) {
+        const message = body.errors.map(e => e.message).join(', ');
+        if (throwOnError) {
+            throw new UnavailableException(message);
+        }
+    }
+    return body;
+}
 
-const BASE_URL = "https://www.dailymotion.com";
-const BASE_URL_API = "https://graphql.api.dailymotion.com";
-const BASE_URL_API_AUTH = `${BASE_URL_API}/oauth/token`;
-const BASE_URL_VIDEO = `${BASE_URL}/video`;
-const BASE_URL_PLAYLIST = `${BASE_URL}/playlist`;
-const BASE_URL_METADATA = `${BASE_URL}/player/metadata/video`;
-const USER_AGENT = 'Mozilla/5.0 (Linux; Android 12) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.6099.230 Mobile Safari/537.36';
-// Those are used even for not logged users to make requests on the graphql api.
-//TODO: check how to get them dynamically
-const CLIENT_ID = 'f1a362d288c1b98099c7';
-const CLIENT_SECRET = 'eea605b96e01c796ff369935357eca920c5da4c5';
-var config = {};
-var _settings = {};
-const X_DM_AppInfo_Id = "com.dailymotion.neon";
-const X_DM_AppInfo_Type = "website";
-const X_DM_AppInfo_Version = "v2024-05-16T12:17:57.363Z"; //TODO check how to get this dynamically
-const X_DM_Neon_SSR = "0";
-const X_DM_Preferred_Country = ""; //TODO check how to get this from Grayjay
-const PLATFORM = "Dailymotion";
-const PLATFORM_CLAIMTYPE = 3;
-const ITEMS_PER_PAGE = 5;
-// search capabilities - upload date
-const LESS_THAN_MINUTE = "LESS_THAN_MINUTE";
-const ONE_TO_FIVE_MINUTES = "ONE_TO_FIVE_MINUTES";
-const FIVE_TO_THIRTY_MINUTES = "FIVE_TO_THIRTY_MINUTES";
-const THIRTY_TO_ONE_HOUR = "THIRTY_TO_ONE_HOUR";
-const MORE_THAN_ONE_HOUR = "MORE_THAN_ONE_HOUR";
-const DURATION_THRESHOLDS = {};
-DURATION_THRESHOLDS[LESS_THAN_MINUTE] = { min: 0, max: 60 };
-DURATION_THRESHOLDS[ONE_TO_FIVE_MINUTES] = { min: 60, max: 300 };
-DURATION_THRESHOLDS[FIVE_TO_THIRTY_MINUTES] = { min: 300, max: 1800 };
-DURATION_THRESHOLDS[THIRTY_TO_ONE_HOUR] = { min: 1800, max: 3600 };
-DURATION_THRESHOLDS[MORE_THAN_ONE_HOUR] = { min: 3600, max: null };
-let AUTHORIZATION_TOKEN_ANONYMOUS_USER = null;
-let AUTHORIZATION_TOKEN_ANONYMOUS_USER_EXPIRATION_DATE = null;
-var httpClientAnonymous = null;
-var httpClientRequestToken = null;
+class SearchPagerAll extends VideoPager {
+    /**
+     * @param {import("./types.d.ts").SearchContext} context the query params
+     * @param {(PlatformVideo | PlatformChannel)[]} results the initial results
+    */
+    cb;
+    constructor(results, hasMore, params, page, cb) {
+        super(results, hasMore, { params, page });
+        this.cb = cb;
+    }
+    nextPage() {
+        this.context.page = this.context.page + 1;
+        const opts = {
+            q: this.context.params.query,
+            sort: this.context.params.sort,
+            page: this.context.page,
+            filters: this.context.params.filters
+        };
+        return this.cb(opts);
+    }
+}
+class SearchChannelPager extends ChannelPager {
+    cb;
+    constructor(results, hasNextPage, params, page, cb) {
+        super(results, hasNextPage, { params, page });
+        this.cb = cb;
+    }
+    nextPage() {
+        const opts = { q: this.context.params.query, page: this.context.page += 1 };
+        return this.cb(opts);
+    }
+}
+class ChannelVideoPager extends VideoPager {
+    /**
+     * @param {import("./types.d.ts").URLContext} context the context
+     * @param {PlatformVideo[]} results the initial results
+     * @param {boolean} hasNextPage if there is a next page
+     */
+    cb;
+    constructor(context, results, hasNextPage, cb) {
+        super(results, hasNextPage, context);
+        this.cb = cb;
+    }
+    nextPage() {
+        return this.cb(this.context);
+    }
+}
+class SearchPlaylistPager extends VideoPager {
+    /**
+     * @param {import("./types.d.ts").SearchContext} context the query params
+     * @param {(PlatformVideo | PlatformChannel)[]} results the initial results
+    */
+    cb;
+    constructor(results, hasMore, params, page, cb) {
+        super(results, hasMore, { params, page });
+        this.cb = cb;
+    }
+    nextPage() {
+        this.context.page = this.context.page + 1;
+        const opts = {
+            q: this.context.params.query,
+            sort: this.context.params.sort,
+            page: this.context.page,
+            filters: this.context.params.filters
+        };
+        // return searchPlaylists(opts);
+        return this.cb(opts);
+    }
+}
+
+var config;
+var _settings;
+let httpClientAnonymous = http.newClient(false);
+// Will be used to store playlists that require authentication
+const authenticatedPlaylistCollection = [];
 source.setSettings = function (settings) {
     _settings = settings;
+    http.GET(BASE_URL, {}, true);
 };
 //Source Methods
 source.enable = function (conf, settings, saveStateStr) {
@@ -1267,9 +1480,15 @@ source.enable = function (conf, settings, saveStateStr) {
         _settings.hideSensitiveContent = false;
         _settings.avatarSize = 8;
         _settings.thumbnailResolution = 7;
+        if (!config) {
+            config = {
+                id: "9c87e8db-e75d-48f4-afe5-2d203d4b95c5"
+            };
+        }
     }
 };
 source.getHome = function () {
+    getAnonymousUserTokenSingleton();
     return getVideoPager({}, 0);
 };
 source.searchSuggestions = function (query) {
@@ -1277,12 +1496,12 @@ source.searchSuggestions = function (query) {
         "query": query
     };
     try {
-        const jsonResponse = executeGqlQuery({
+        const jsonResponse = executeGqlQuery(getHttpContext({ usePlatformAuth: false }), {
             operationName: 'AUTOCOMPLETE_QUERY',
             variables: variables,
             query: SEARCH_SUGGESTIONS_QUERY
         });
-        return jsonResponse?.data?.search?.suggestedVideos?.edges?.map(edge => edge?.node?.name);
+        return jsonResponse?.data?.search?.suggestedVideos?.edges?.map(edge => edge?.node?.name ?? "") ?? [];
     }
     catch (error) {
         log('Failed to get search suggestions:' + error?.message);
@@ -1331,10 +1550,6 @@ source.getSearchCapabilities = () => {
 source.search = function (query, type, order, filters) {
     return getSearchPagerAll({ q: query, page: 1, type, order, filters });
 };
-// source.getSearchChannelContentsCapabilities = function () {
-// };
-// source.searchChannelContents = function (channelUrl, query, type, order, filters) {
-// };
 source.searchChannels = function (query) {
     return getSearchChannelPager({ q: query, page: 1 });
 };
@@ -1344,17 +1559,16 @@ source.isChannelUrl = function (url) {
 };
 source.getChannel = function (url) {
     const channel_name = getChannelNameFromUrl(url);
-    const channelDetails = executeGqlQuery({
+    const channelDetails = executeGqlQuery(getHttpContext({ usePlatformAuth: false }), {
         operationName: 'CHANNEL_QUERY_DESKTOP',
         variables: {
             channel_name: channel_name,
-            avatar_size: constants.creatorAvatarHeight[_settings?.avatarSize]
+            avatar_size: creatorAvatarHeight[_settings?.avatarSize]
         },
         query: CHANNEL_BY_URL_QUERY
     });
-    const user = channelDetails.data.channel;
-    const banner = user?.coverURL1024x ?? user?.coverURL1920x;
-    const externalLinks = user?.externalLinks ?? {};
+    const channel = channelDetails.data.channel;
+    const externalLinks = channel?.externalLinks ?? {};
     const links = {};
     Object
         .keys(externalLinks)
@@ -1364,12 +1578,12 @@ source.getChannel = function (url) {
         }
     });
     return new PlatformChannel({
-        id: new PlatformID(PLATFORM, user?.id, config?.id, PLATFORM_CLAIMTYPE),
-        name: user?.displayName,
-        thumbnail: user?.avatar?.url,
-        banner,
-        subscribers: user?.metrics?.engagement?.followers?.edges[0]?.node?.total,
-        description: user?.description,
+        id: new PlatformID(PLATFORM, channel?.id, config.id, PLATFORM_CLAIMTYPE),
+        name: channel?.displayName ?? "",
+        thumbnail: channel?.avatar?.url ?? "",
+        banner: channel.banner?.url ?? "",
+        subscribers: channel?.metrics?.engagement?.followers?.edges[0]?.node?.total ?? 0,
+        description: channel?.description ?? "",
         url,
         links,
     });
@@ -1386,8 +1600,7 @@ source.getContentDetails = function (url) {
 };
 //Playlist
 source.isPlaylistUrl = (url) => {
-    var isPlaylist = url.startsWith(BASE_URL_PLAYLIST);
-    return isPlaylist;
+    return url.startsWith(BASE_URL_PLAYLIST);
 };
 source.searchPlaylists = (query, type, order, filters) => {
     return searchPlaylists({ q: query, type, order, filters });
@@ -1396,27 +1609,29 @@ source.getPlaylist = (url) => {
     const xid = url.split('/').pop();
     const variables = {
         xid,
-        avatar_size: constants.creatorAvatarHeight[_settings?.avatarSize],
-        thumbnail_resolution: constants.thumbnailHeight[_settings?.thumbnailResolution],
+        avatar_size: creatorAvatarHeight[_settings.avatarSize],
+        thumbnail_resolution: thumbnailHeight[_settings.thumbnailResolution],
     };
-    const jsonResponse = executeGqlQuery({
+    const usePlatformAuth = authenticatedPlaylistCollection.includes(url);
+    let jsonResponse = executeGqlQuery(getHttpContext({ usePlatformAuth }), {
         operationName: 'PLAYLIST_VIDEO_QUERY',
         variables,
-        query: PLAYLIST_DETAILS_QUERY
+        query: PLAYLIST_DETAILS_QUERY,
+        usePlatformAuth
     });
     const videos = jsonResponse?.data?.collection?.videos?.edges.map(edge => {
         const resource = edge.node;
         const opts = {
             id: new PlatformID(PLATFORM, resource.id, config.id, PLATFORM_CLAIMTYPE),
-            name: resource.title,
+            name: resource.title ?? "",
             thumbnails: new Thumbnails([
-                new Thumbnail(resource?.thumbnail?.url, 0)
+                new Thumbnail(resource?.thumbnail?.url ?? "", 0)
             ]),
-            author: new PlatformAuthorLink(new PlatformID(PLATFORM, resource.creator.id, config.id, PLATFORM_CLAIMTYPE), resource.creator.displayName, `${BASE_URL}/${resource.creator.name}`, resource.creator.avatar.url ?? "", 0),
+            author: new PlatformAuthorLink(new PlatformID(PLATFORM, resource?.creator?.id ?? "", config.id, PLATFORM_CLAIMTYPE), resource?.creator?.displayName ?? "", `${BASE_URL}/${resource?.creator?.name}`, resource?.creator?.avatar?.url ?? "", 0),
             uploadDate: parseInt(new Date(resource.createdAt).getTime() / 1000),
             datetime: parseInt(new Date(resource.createdAt).getTime() / 1000),
-            url: resource.url,
-            duration: resource.duration,
+            url: resource.url ?? "",
+            duration: resource.duration ?? 0,
             viewCount: resource?.viewCount ?? 0,
             isLive: false
         };
@@ -1425,8 +1640,8 @@ source.getPlaylist = (url) => {
     const playlist = jsonResponse?.data?.collection;
     return new PlatformPlaylistDetails({
         url: `${BASE_URL_PLAYLIST}/${playlist?.xid}`,
-        id: new PlatformID(PLATFORM, playlist?.xid, config.id),
-        author: new PlatformAuthorLink(new PlatformID(PLATFORM, playlist?.creator?.id, config.id, PLATFORM_CLAIMTYPE), playlist?.creator?.displayName, `${BASE_URL}/${playlist?.creator?.name}`, playlist?.creator?.avatar?.url ?? "", 0),
+        id: new PlatformID(PLATFORM, playlist?.xid, config.id, PLATFORM_CLAIMTYPE),
+        author: new PlatformAuthorLink(new PlatformID(PLATFORM, playlist?.creator?.id ?? "", config.id, PLATFORM_CLAIMTYPE), playlist?.creator?.displayName ?? "", `${BASE_URL}/${playlist?.creator?.name}`, playlist?.creator?.avatar?.url ?? "", 0),
         name: playlist.name,
         thumbnail: playlist?.thumbnail?.url,
         videoCount: playlist?.metrics?.engagement?.videos?.edges[0]?.node?.total,
@@ -1448,7 +1663,7 @@ source.getUserSubscriptions = () => {
         'X-DM-AppInfo-Type': X_DM_AppInfo_Type,
         'X-DM-AppInfo-Version': X_DM_AppInfo_Version,
         'X-DM-Neon-SSR': '0',
-        'X-DM-Preferred-Country': 'it',
+        'X-DM-Preferred-Country': getPreferredCountry(_settings?.preferredCountry),
         Origin: BASE_URL,
         DNT: '1',
         Connection: 'keep-alive',
@@ -1459,18 +1674,20 @@ source.getUserSubscriptions = () => {
         Pragma: 'no-cache',
         'Cache-Control': 'no-cache',
     };
+    const usePlatformAuth = true;
     const fetchSubscriptions = (page, first) => {
-        const jsonResponse = executeGqlQuery({
+        const jsonResponse = executeGqlQuery(getHttpContext({ usePlatformAuth }), {
             operationName: 'SUBSCRIPTIONS_QUERY',
             variables: {
                 first: first,
                 page: page,
-                avatar_size: constants.creatorAvatarHeight[_settings?.avatarSize],
+                avatar_size: creatorAvatarHeight[_settings?.avatarSize],
             },
             headers,
-            query: GET_USER_SUBSCRIPTIONS
-        }, true);
-        return jsonResponse?.data?.me?.channel?.followings?.edges?.map(edge => edge.node.creator.name);
+            query: GET_USER_SUBSCRIPTIONS,
+            usePlatformAuth
+        });
+        return jsonResponse?.data?.me?.channel?.followings?.edges?.map(edge => edge?.node?.creator?.name ?? "") ?? [];
     };
     const first = 100; // Number of records to fetch per page
     let page = 1;
@@ -1487,6 +1704,73 @@ source.getUserSubscriptions = () => {
     } while (items.length);
     return subscriptions;
 };
+source.getUserPlaylists = () => {
+    if (!bridge.isLoggedIn()) {
+        bridge.log("Failed to retrieve subscriptions page because not logged in.");
+        throw new ScriptException("Not logged in");
+    }
+    const headers = {
+        'Content-Type': 'application/json',
+        'User-Agent': USER_AGENT,
+        // Accept: '*/*, */*',
+        'Accept-Language': 'en-GB',
+        Referer: `${BASE_URL}/library/subscriptions`,
+        'X-DM-AppInfo-Id': X_DM_AppInfo_Id,
+        'X-DM-AppInfo-Type': X_DM_AppInfo_Type,
+        'X-DM-AppInfo-Version': X_DM_AppInfo_Version,
+        'X-DM-Neon-SSR': '0',
+        'X-DM-Preferred-Country': getPreferredCountry(_settings?.preferredCountry),
+        Origin: BASE_URL,
+        DNT: '1',
+        Connection: 'keep-alive',
+        'Sec-Fetch-Dest': 'empty',
+        'Sec-Fetch-Mode': 'cors',
+        'Sec-Fetch-Site': 'same-site',
+        Priority: 'u=4',
+        Pragma: 'no-cache',
+        'Cache-Control': 'no-cache',
+    };
+    const userInfoQuery = `
+	query SUBSCRIPTIONS_QUERY {
+		me {
+			xid
+			channel {
+				name
+			}
+		}
+	}	
+	`;
+    const jsonResponse = executeGqlQuery(getHttpContext({ usePlatformAuth: true }), {
+        operationName: 'SUBSCRIPTIONS_QUERY',
+        headers,
+        query: userInfoQuery,
+        usePlatformAuth: true
+    });
+    const userName = jsonResponse?.data?.me?.channel?.name;
+    return getPlaylistsByUsername(userName, headers, true);
+};
+function getPlaylistsByUsername(userName, headers, usePlatformAuth = false) {
+    const jsonResponse1 = executeGqlQuery(getHttpContext({ usePlatformAuth }), {
+        operationName: 'CHANNEL_PLAYLISTS_QUERY',
+        variables: {
+            channel_name: userName,
+            sort: "recent",
+            page: 1,
+            first: 99
+        },
+        headers,
+        query: GET_CHANNEL_PLAYLISTS,
+        usePlatformAuth
+    });
+    const playlists = jsonResponse1.data.channel.channel_playlist_collections.edges.map(edge => {
+        const playlistUrl = `${BASE_URL_PLAYLIST}/${edge.node.xid}`;
+        if (!authenticatedPlaylistCollection.includes(playlistUrl)) {
+            authenticatedPlaylistCollection.push(playlistUrl);
+        }
+        return playlistUrl;
+    });
+    return playlists;
+}
 function getQuery(context) {
     context.sort = parseSort(context.order);
     if (!context.filters) {
@@ -1523,27 +1807,28 @@ function searchPlaylists(contextQuery) {
         "shouldIncludeLives": false,
         "page": context.page,
         "limit": ITEMS_PER_PAGE,
-        "thumbnail_resolution": constants.thumbnailHeight[_settings?.thumbnailResolution],
-        "avatar_size": constants.creatorAvatarHeight[_settings?.avatarSize],
+        "thumbnail_resolution": thumbnailHeight[_settings?.thumbnailResolution],
+        "avatar_size": creatorAvatarHeight[_settings?.avatarSize],
     };
-    const jsonResponse = executeGqlQuery({
+    const jsonResponse = executeGqlQuery(getHttpContext({ usePlatformAuth: false }), {
         operationName: 'SEARCH_QUERY',
         variables: variables,
         query: MAIN_SEARCH_QUERY,
         headers: undefined
     });
-    var searchResults = jsonResponse?.data?.search?.playlists?.edges?.map(edge => {
-        const playlist = edge.node;
+    const playlistConnection = jsonResponse?.data?.search?.playlists;
+    var searchResults = playlistConnection?.edges?.map(edge => {
+        const playlist = edge?.node;
         return new PlatformPlaylist({
             url: `${BASE_URL_PLAYLIST}/${playlist?.xid}`,
-            id: new PlatformID(PLATFORM, playlist?.xid, config.id),
-            author: new PlatformAuthorLink(new PlatformID(PLATFORM, playlist.creator.id, config.id, PLATFORM_CLAIMTYPE), playlist.creator.displayName, `${BASE_URL}/${playlist.creator.name}`, playlist.creator.avatar.url ?? "", 0),
-            name: playlist.name,
+            id: new PlatformID(PLATFORM, playlist?.xid ?? "", config.id, PLATFORM_CLAIMTYPE),
+            author: new PlatformAuthorLink(new PlatformID(PLATFORM, playlist?.creator?.id ?? "", config.id, PLATFORM_CLAIMTYPE), playlist?.creator?.displayName ?? "", `${BASE_URL}/${playlist?.creator?.name}`, playlist?.creator?.avatar?.url ?? "", 0),
+            name: playlist?.name,
             thumbnail: playlist?.thumbnail?.url,
             videoCount: playlist?.metrics?.engagement?.videos?.edges[0]?.node?.total,
         });
     });
-    const hasMore = jsonResponse?.data?.search?.playlists?.pageInfo?.hasNextPage;
+    const hasMore = playlistConnection?.pageInfo?.hasNextPage;
     if (!searchResults || !searchResults?.length) {
         return new PlaylistPager([]);
     }
@@ -1552,71 +1837,9 @@ function searchPlaylists(contextQuery) {
         sort: context.sort,
         filters: context.filters,
     };
-    return new SearchPlaylistPager(searchResults, hasMore, params, context.page);
+    return new SearchPlaylistPager(searchResults, hasMore, params, context.page, searchPlaylists);
 }
 //Internals
-function getChannelNameFromUrl(url) {
-    const channel_name = url.split('/').pop();
-    return channel_name;
-}
-function isUsernameUrl(url) {
-    // Define the regex pattern to match the username URL
-    var regex = new RegExp('^' + BASE_URL.replace(/\./g, '\\.') + '/[^/]+$');
-    // Test the URL against the regex pattern
-    return regex.test(url);
-}
-function getAnonymousUserTokenSingleton() {
-    // Check if the anonymous user token is available and not expired
-    if (AUTHORIZATION_TOKEN_ANONYMOUS_USER) {
-        const isTokenValid = AUTHORIZATION_TOKEN_ANONYMOUS_USER_EXPIRATION_DATE && new Date().getTime() < AUTHORIZATION_TOKEN_ANONYMOUS_USER_EXPIRATION_DATE;
-        if (isTokenValid) {
-            return AUTHORIZATION_TOKEN_ANONYMOUS_USER;
-        }
-    }
-    // Prepare the request body for obtaining a new token
-    const body = util.objectToUrlEncodedString({
-        client_id: CLIENT_ID,
-        client_secret: CLIENT_SECRET,
-        grant_type: 'client_credentials'
-    });
-    // Make the HTTP POST request to the authorization API
-    const res = httpClientRequestToken.POST(`${BASE_URL_API_AUTH}`, body, {
-        'User-Agent': USER_AGENT,
-        'Content-Type': 'application/x-www-form-urlencoded',
-        'Origin': BASE_URL,
-        'DNT': '1',
-        'Sec-GPC': '1',
-        'Connection': 'keep-alive',
-        'Sec-Fetch-Dest': 'empty',
-        'Sec-Fetch-Mode': 'cors',
-        'Sec-Fetch-Site': 'same-site',
-        'Priority': 'u=4',
-        'Pragma': 'no-cache',
-        'Cache-Control': 'no-cache'
-    }, false);
-    // Check if the response code indicates success
-    if (res.code !== 200) {
-        console.error('Failed to get token', res);
-        throw new ScriptException("", "Failed to get token: " + res.code + " - " + res.body);
-    }
-    // Parse the response JSON to extract the token information
-    const json = JSON.parse(res.body);
-    // Ensure the response contains the necessary token information
-    if (!json.token_type || !json.access_token) {
-        console.error('Invalid token response', res);
-        throw new ScriptException("", 'Invalid token response: ' + res.body);
-    }
-    // Store the token and its expiration date
-    AUTHORIZATION_TOKEN_ANONYMOUS_USER = `${json.token_type} ${json.access_token}`;
-    AUTHORIZATION_TOKEN_ANONYMOUS_USER_EXPIRATION_DATE = new Date().getTime() + (json.expires_in * 1000);
-    return AUTHORIZATION_TOKEN_ANONYMOUS_USER;
-}
-function getPreferredCountry() {
-    const countryName = constants.countryNames[_settings?.preferredCountry];
-    const code = constants.countryNamesToCode[countryName];
-    const preferredCountry = (code || X_DM_Preferred_Country || '').toLowerCase();
-    return preferredCountry;
-}
 function getVideoPager(params, page) {
     const count = ITEMS_PER_PAGE;
     if (!params) {
@@ -1632,7 +1855,7 @@ function getVideoPager(params, page) {
         "X-DM-AppInfo-Type": X_DM_AppInfo_Type,
         "X-DM-AppInfo-Version": X_DM_AppInfo_Version,
         "X-DM-Neon-SSR": X_DM_Neon_SSR,
-        "X-DM-Preferred-Country": getPreferredCountry(),
+        "X-DM-Preferred-Country": getPreferredCountry(_settings?.preferredCountry),
         "Origin": BASE_URL,
         "DNT": "1",
         "Sec-Fetch-Site": "same-site",
@@ -1642,12 +1865,12 @@ function getVideoPager(params, page) {
     };
     let obj;
     try {
-        obj = executeGqlQuery({
+        obj = executeGqlQuery(getHttpContext({ usePlatformAuth: false }), {
             operationName: 'SEACH_DISCOVERY_QUERY',
             variables: {
                 shouldQueryPromotedHashtag: false,
-                avatar_size: constants.creatorAvatarHeight[_settings?.avatarSize],
-                thumbnail_resolution: constants.thumbnailHeight[_settings?.thumbnailResolution],
+                avatar_size: creatorAvatarHeight[_settings?.avatarSize],
+                thumbnail_resolution: thumbnailHeight[_settings?.thumbnailResolution],
             },
             query: HOME_QUERY,
             headers: headersToAdd,
@@ -1661,7 +1884,7 @@ function getVideoPager(params, page) {
         ?.filter(edge => edge?.node?.id)
         ?.map(edge => {
         const v = edge.node;
-        const metadata = GetVideoExtraDEtails(v.xid);
+        const metadata = GetVideoExtraDetails(v.xid);
         return ToPlatformVideo({
             id: v.id,
             name: v.title ?? "",
@@ -1680,10 +1903,10 @@ function getVideoPager(params, page) {
         });
     });
     const hasMore = obj?.data?.home?.neon?.sections?.edges[0]?.node?.components?.pageInfo?.hasNextPage ?? false;
-    return new SearchPagerAll(results, hasMore, params, page);
+    return new SearchPagerAll(results, hasMore, params, page, getVideoPager);
 }
-function GetVideoExtraDEtails(xid) {
-    const json = executeGqlQuery({
+function GetVideoExtraDetails(xid) {
+    const json = executeGqlQuery(getHttpContext({ usePlatformAuth: false }), {
         operationName: 'WATCHING_VIDEO',
         variables: { xid },
         query: GET_VIDEO_EXTRA_DETAILS
@@ -1695,7 +1918,7 @@ function GetVideoExtraDEtails(xid) {
 function getChannelPager(context) {
     const url = context.url;
     const channel_name = getChannelNameFromUrl(url);
-    const json = executeGqlQuery({
+    const json = executeGqlQuery(getHttpContext({ usePlatformAuth: false }), {
         operationName: 'CHANNEL_VIDEOS_QUERY',
         variables: {
             "channel_name": channel_name,
@@ -1703,26 +1926,27 @@ function getChannelPager(context) {
             "page": context.page ?? 1,
             "allowExplicit": !_settings.hideSensitiveContent,
             "first": context.page_size ?? ITEMS_PER_PAGE,
-            "avatar_size": constants.creatorAvatarHeight[_settings?.avatarSize],
-            "thumbnail_resolution": constants.thumbnailHeight[_settings?.thumbnailResolution],
+            "avatar_size": creatorAvatarHeight[_settings?.avatarSize],
+            "thumbnail_resolution": thumbnailHeight[_settings?.thumbnailResolution],
         },
         query: CHANNEL_VIDEOS_BY_CHANNEL_NAME
     });
     const edges = json?.data?.channel?.channel_videos_all_videos?.edges ?? [];
     let videos = edges.map((edge) => {
-        const metadata = GetVideoExtraDEtails(edge.node.xid);
+        const video = edge.node;
+        const metadata = GetVideoExtraDetails(video.xid);
         return ToPlatformVideo({
-            id: edge.node.id,
-            name: edge.node.title,
-            thumbnail: edge?.node?.thumbnail.url ?? "",
-            createdAt: edge?.node?.createdAt,
-            creatorId: edge?.node?.creator?.id,
-            creatorDisplayName: edge?.node?.creator?.displayName,
-            creatorName: edge.node.creator.name,
-            creatorAvatar: edge?.node?.creator?.avatar?.url,
-            creatorUrl: `${BASE_URL}/${edge?.node?.creator?.name}`,
-            duration: edge.node.duration,
-            url: `${BASE_URL_VIDEO}/${edge?.node?.xid}`,
+            id: video.id,
+            name: video.title,
+            thumbnail: video?.thumbnail?.url ?? "",
+            createdAt: video?.createdAt,
+            creatorId: video?.creator?.id,
+            creatorDisplayName: video?.creator?.displayName,
+            creatorName: video?.creator?.name,
+            creatorAvatar: video?.creator?.avatar?.url,
+            creatorUrl: `${BASE_URL}/${video?.creator?.name}`,
+            duration: video.duration,
+            url: `${BASE_URL_VIDEO}/${video?.xid}`,
             viewCount: metadata.views ?? 0,
             isLive: false
         });
@@ -1730,10 +1954,10 @@ function getChannelPager(context) {
     if (edges.length > 0) {
         context.page++;
     }
-    return new ChannelVideoPager(context, videos, json?.data?.channel?.channel_videos_all_videos?.pageInfo?.hasNextPage);
+    return new ChannelVideoPager(context, videos, json?.data?.channel?.channel_videos_all_videos?.pageInfo?.hasNextPage, getChannelPager);
 }
 function ToPlatformVideo(resource) {
-    const opts = {
+    return new PlatformVideo({
         id: new PlatformID(PLATFORM, resource.id, config.id, PLATFORM_CLAIMTYPE),
         name: resource.name,
         thumbnails: new Thumbnails([new Thumbnail(resource.thumbnail, 0)]),
@@ -1743,8 +1967,7 @@ function ToPlatformVideo(resource) {
         duration: resource.duration,
         viewCount: resource.viewCount,
         isLive: resource.isLive
-    };
-    return new PlatformVideo(opts);
+    });
 }
 function parseSort(order) {
     let sort;
@@ -1806,37 +2029,39 @@ function getSearchPagerAll(contextQuery) {
         "shouldIncludeLives": true,
         "page": context.page ?? 1,
         "limit": ITEMS_PER_PAGE,
-        "avatar_size": constants.creatorAvatarHeight[_settings?.avatarSize],
-        "thumbnail_resolution": constants.thumbnailHeight[_settings?.thumbnailResolution]
+        "avatar_size": creatorAvatarHeight[_settings?.avatarSize],
+        "thumbnail_resolution": thumbnailHeight[_settings?.thumbnailResolution]
     };
-    const jsonResponse = executeGqlQuery({
+    const jsonResponse = executeGqlQuery(getHttpContext({ usePlatformAuth: false }), {
         operationName: 'SEARCH_QUERY',
         variables: variables,
         query: MAIN_SEARCH_QUERY,
         headers: undefined
     });
     const results = [];
+    const videoConnection = jsonResponse?.data?.search?.videos;
+    const liveConnection = jsonResponse?.data?.search?.videos;
     const all = [
-        ...(jsonResponse?.data?.search?.videos?.edges ?? []),
-        ...(jsonResponse?.data?.search?.lives?.edges ?? [])
+        ...(videoConnection?.edges ?? []),
+        ...(liveConnection?.edges ?? [])
     ];
     for (const edge of all) {
-        const sv = edge.node;
-        const isLive = sv.isOnAir == true;
-        const viewCount = isLive ? sv.audienceCount : sv?.stats?.views?.total;
+        const sv = edge?.node;
+        const isLive = sv?.isOnAir == true;
+        const viewCount = isLive ? sv?.audienceCount : sv?.stats?.views?.total;
         var video = ToPlatformVideo({
-            id: sv.id,
-            name: sv.title,
+            id: sv?.id,
+            name: sv?.title,
             thumbnail: sv?.thumbnail?.url,
-            createdAt: sv.createdAt,
-            creatorId: sv.creator?.id,
-            creatorName: sv.creator?.name,
-            creatorDisplayName: sv.creator?.displayName,
+            createdAt: sv?.createdAt,
+            creatorId: sv?.creator?.id,
+            creatorName: sv?.creator?.name,
+            creatorDisplayName: sv?.creator?.displayName,
             creatorUrl: `${BASE_URL}/${sv?.creator?.name}`,
-            creatorAvatar: sv.creator?.avatar?.url ?? "",
-            duration: sv.duration,
+            creatorAvatar: sv?.creator?.avatar?.url ?? "",
+            duration: sv?.duration,
             viewCount,
-            url: `${BASE_URL_VIDEO}/${sv.xid}`,
+            url: `${BASE_URL_VIDEO}/${sv?.xid}`,
             isLive,
             description: sv?.description ?? '',
         });
@@ -1848,45 +2073,11 @@ function getSearchPagerAll(contextQuery) {
         sort: context.sort,
         filters: context.filters,
     };
-    return new SearchPagerAll(results, jsonResponse?.data?.search?.videos?.pageInfo?.hasNextPage, params, context.page);
+    return new SearchPagerAll(results, videoConnection?.pageInfo?.hasNextPage, params, context.page, getSearchPagerAll);
 }
-function executeGqlQuery(requestOptions, usePlatformAuth = false) {
-    const headersToAdd = requestOptions.headers || {
-        "User-Agent": USER_AGENT,
-        "Accept": "*/*",
-        // "Accept-Language": Accept_Language,
-        "Referer": BASE_URL,
-        "Origin": BASE_URL,
-        "DNT": "1",
-        "Connection": "keep-alive",
-        "Sec-Fetch-Dest": "empty",
-        "Sec-Fetch-Mode": "cors",
-        "Sec-Fetch-Site": "same-site",
-        "Pragma": "no-cache",
-        "Cache-Control": "no-cache"
-    };
-    const gql = JSON.stringify({
-        operationName: requestOptions.operationName,
-        variables: requestOptions.variables,
-        query: requestOptions.query,
-    });
-    const res = getHttpContext(usePlatformAuth).POST(BASE_URL_API, gql, headersToAdd, usePlatformAuth);
-    if (!res.isOk) {
-        console.error('Failed to get token', res);
-        throw new ScriptException("Failed to get token", res);
-    }
-    const body = JSON.parse(res.body);
-    // some errors may be returned in the body with a status code 200
-    if (body.errors) {
-        const message = body.errors.map(e => e.message).join(', ');
-        log(JSON.stringify(message));
-        throw new UnavailableException(message);
-    }
-    return body;
-}
-function checkHLS(url, headersToAdd, use_authenticated = false) {
+function checkHLS(url, headersToAdd, usePlatformAuth = false) {
     // const resp = http.GET(url, headersToAdd, true);
-    var resp = getHttpContext(use_authenticated).GET(url, headersToAdd, use_authenticated, use_authenticated);
+    var resp = getHttpContext({ usePlatformAuth }).GET(url, headersToAdd, usePlatformAuth);
     if (!resp.isOk) {
         throw new UnavailableException('This content is not available');
     }
@@ -1915,7 +2106,7 @@ function getSavedVideo(url, usePlatformAuth = false) {
     else {
         headers1["Cookie"] = "ff=off";
     }
-    var player_metadataResponse = getHttpContext(usePlatformAuth).GET(player_metadata_url, headers1, usePlatformAuth);
+    var player_metadataResponse = getHttpContext({ usePlatformAuth }).GET(player_metadata_url, headers1, usePlatformAuth);
     if (!player_metadataResponse.isOk) {
         throw new UnavailableException('Unable to get player metadata');
     }
@@ -1938,7 +2129,7 @@ function getSavedVideo(url, usePlatformAuth = false) {
         "X-DM-AppInfo-Type": X_DM_AppInfo_Type,
         "X-DM-AppInfo-Version": X_DM_AppInfo_Version,
         "X-DM-Neon-SSR": X_DM_Neon_SSR,
-        "X-DM-Preferred-Country": getPreferredCountry(),
+        "X-DM-Preferred-Country": getPreferredCountry(_settings?.preferredCountry),
         "Origin": BASE_URL,
         "DNT": "1",
         "Connection": "keep-alive",
@@ -1955,15 +2146,15 @@ function getSavedVideo(url, usePlatformAuth = false) {
     const variables = {
         "xid": id,
         "isSEO": false,
-        "avatar_size": constants.creatorAvatarHeight[_settings?.avatarSize],
-        "thumbnail_resolution": constants.thumbnailHeight[_settings?.thumbnailResolution]
+        "avatar_size": creatorAvatarHeight[_settings?.avatarSize],
+        "thumbnail_resolution": thumbnailHeight[_settings?.thumbnailResolution]
     };
     const videoDetailsRequestBody = JSON.stringify({
         operationName: "WATCHING_VIDEO",
         variables,
         query: VIDEO_DETAILS_QUERY
     });
-    const video_details_response = getHttpContext(usePlatformAuth).POST(BASE_URL_API, videoDetailsRequestBody, videoDetailsRequestHeaders, usePlatformAuth);
+    const video_details_response = getHttpContext({ usePlatformAuth }).POST(BASE_URL_API, videoDetailsRequestBody, videoDetailsRequestHeaders, usePlatformAuth);
     if (video_details_response.code != 200) {
         throw new UnavailableException('Failed to get video details');
     }
@@ -2027,9 +2218,9 @@ function getSearchChannelPager(context) {
         query: context.q,
         page: context.page ?? 1,
         limit: ITEMS_PER_PAGE,
-        avatar_size: constants.creatorAvatarHeight[_settings?.avatarSize]
+        avatar_size: creatorAvatarHeight[_settings?.avatarSize]
     };
-    const json = executeGqlQuery({
+    const json = executeGqlQuery(getHttpContext({ usePlatformAuth: false }), {
         operationName: "SEARCH_QUERY",
         variables,
         query: SEARCH_CHANNEL
@@ -2043,114 +2234,16 @@ function getSearchChannelPager(context) {
             subscribers: c?.metrics?.engagement?.followers?.edges[0]?.node?.total ?? 0,
             url: `${BASE_URL}/${c.name}`,
             links: [],
-            banner: null,
+            banner: "",
             description: c.description,
         });
     });
     var params = {
         query: context.q,
     };
-    return new SearchChannelPager(results, json?.data?.search?.channels?.pageInfo?.hasNextPage, params, context.page);
-}
-function getHttpContext(usePlatformAuth = false) {
-    return usePlatformAuth ? http : httpClientAnonymous;
-}
-function ensureDefaultSettings() {
-    if (!_settings) {
-        _settings = {};
-    }
-    if (_settings.hideSensitiveContent == undefined) {
-        _settings.hideSensitiveContent = true;
-    }
-    if (_settings.avatarSize == undefined) {
-        _settings.avatarSize = 8;
-    }
-    if (_settings.thumbnailResolution == undefined) {
-        _settings.thumbnailResolution = 7;
-    }
-    if (_settings.preferredCountry == undefined) {
-        const settingIndex = constants?.countryNames?.indexOf('');
-        _settings.preferredCountry = settingIndex;
-    }
-}
-function ensureInitHttpClients() {
-    try {
-        if (!httpClientRequestToken) {
-            httpClientRequestToken = http.newClient(false);
-            httpClientAnonymous = http.newClient(false);
-            const authorization = getAnonymousUserTokenSingleton();
-            httpClientAnonymous.setDefaultHeaders({ 'Authorization': authorization });
-        }
-    }
-    catch (e) {
-        // log(e.message)
-    }
-}
-function ensureDefaults() {
-    ensureDefaultSettings();
-    ensureInitHttpClients();
-}
-//Pagers
-class SearchPagerAll extends VideoPager {
-    /**
-     * @param {import("./types.d.ts").SearchContext} context the query params
-     * @param {(PlatformVideo | PlatformChannel)[]} results the initial results
-    */
-    constructor(results, hasMore, params, page) {
-        super(results, hasMore, { params, page });
-    }
-    nextPage() {
-        this.context.page = this.context.page + 1;
-        const opts = {
-            q: this.context.params.query,
-            sort: this.context.params.sort,
-            page: this.context.page,
-            filters: this.context.params.filters
-        };
-        return getSearchPagerAll(opts);
-    }
+    return new SearchChannelPager(results, json?.data?.search?.channels?.pageInfo?.hasNextPage, params, context.page, getSearchChannelPager);
 }
-class SearchChannelPager extends ChannelPager {
-    constructor(results, hasNextPage, params, page) {
-        super(results, hasNextPage, { params, page });
-    }
-    nextPage() {
-        const opts = { q: this.context.params.query, page: this.context.page += 1 };
-        return getSearchChannelPager(opts);
-    }
-}
-class ChannelVideoPager extends VideoPager {
-    /**
-     * @param {import("./types.d.ts").URLContext} context the context
-     * @param {PlatformVideo[]} results the initial results
-     * @param {boolean} hasNextPage if there is a next page
-     */
-    constructor(context, results, hasNextPage) {
-        super(results, hasNextPage, context);
-    }
-    nextPage() {
-        return getChannelPager(this.context);
-    }
-}
-class SearchPlaylistPager extends VideoPager {
-    /**
-     * @param {import("./types.d.ts").SearchContext} context the query params
-     * @param {(PlatformVideo | PlatformChannel)[]} results the initial results
-    */
-    constructor(results, hasMore, params, page) {
-        super(results, hasMore, { params, page });
-    }
-    nextPage() {
-        this.context.page = this.context.page + 1;
-        const opts = {
-            q: this.context.params.query,
-            sort: this.context.params.sort,
-            page: this.context.page,
-            filters: this.context.params.filters
-        };
-        return searchPlaylists(opts);
-    }
+function getHttpContext(opts = { usePlatformAuth: false }) {
+    return opts.usePlatformAuth ? http : httpClientAnonymous;
 }
-//wip
-ensureDefaults();
 log("LOADED");
diff --git a/src/DailymotionScript.ts b/src/DailymotionScript.ts
index 5c4a10ff8db39862f3ca5c8af007e877bfcfc864..a8567e789579b23a70b3664dee46d5ec678531fa 100644
--- a/src/DailymotionScript.ts
+++ b/src/DailymotionScript.ts
@@ -1,14 +1,10 @@
 var config: Config;
 var _settings: DailymotionPluginSettings;
 
-let AUTHORIZATION_TOKEN_ANONYMOUS_USER: string = "";
-let AUTHORIZATION_TOKEN_ANONYMOUS_USER_EXPIRATION_DATE: number;
 
 import {
 	creatorAvatarHeight,
 	thumbnailHeight,
-	countryNames,
-	countryNamesToCode,
 	BASE_URL,
 	LESS_THAN_MINUTE,
 	ONE_TO_FIVE_MINUTES,
@@ -26,10 +22,6 @@ import {
 	X_DM_AppInfo_Version,
 	X_DM_Neon_SSR,
 	DURATION_THRESHOLDS,
-	CLIENT_ID,
-	CLIENT_SECRET,
-	BASE_URL_API_AUTH,
-	X_DM_Preferred_Country,
 	BASE_URL_API,
 	BASE_URL_METADATA,
 	errorTypes,
@@ -50,11 +42,11 @@ import {
 } from './gqlQueries';
 
 import {
-	objectToUrlEncodedString,
 	getChannelNameFromUrl,
 	isUsernameUrl,
 	executeGqlQuery,
-	getPreferredCountry
+	getPreferredCountry,
+	getAnonymousUserTokenSingleton
 } from './util';
 
 import {
@@ -77,9 +69,8 @@ import {
 } from './Pagers';
 
 
-let httpClientAnonymous: IHttp
+let httpClientAnonymous: IHttp = http.newClient(false);
 
-var httpClientRequestToken = null;
 
 // Will be used to store playlists that require authentication
 const authenticatedPlaylistCollection: string[] = [];
@@ -101,14 +92,18 @@ source.enable = function (conf, settings, saveStateStr) {
 		_settings.thumbnailResolution = 7;
 
 		if (!config) {
-			config = {}
+			config = {
+				id: "9c87e8db-e75d-48f4-afe5-2d203d4b95c5"
+			}
 		}
-		config.id = "9c87e8db-e75d-48f4-afe5-2d203d4b95c5"
 	}
 }
 
 
 source.getHome = function () {
+
+	getAnonymousUserTokenSingleton();
+
 	return getVideoPager({}, 0);
 };
 
@@ -267,7 +262,7 @@ source.getPlaylist = (url: string): PlatformPlaylistDetails => {
 	}
 
 	const usePlatformAuth = authenticatedPlaylistCollection.includes(url);
-	
+
 	let jsonResponse = executeGqlQuery(
 		getHttpContext({ usePlatformAuth }),
 		{
@@ -340,7 +335,7 @@ source.getUserSubscriptions = (): string[] => {
 		'X-DM-AppInfo-Type': X_DM_AppInfo_Type,
 		'X-DM-AppInfo-Version': X_DM_AppInfo_Version,
 		'X-DM-Neon-SSR': '0',
-		'X-DM-Preferred-Country': 'it',
+		'X-DM-Preferred-Country': getPreferredCountry(_settings?.preferredCountry),
 		Origin: BASE_URL,
 		DNT: '1',
 		Connection: 'keep-alive',
@@ -352,10 +347,11 @@ source.getUserSubscriptions = (): string[] => {
 		'Cache-Control': 'no-cache',
 	}
 
+	const usePlatformAuth = true;
 
 	const fetchSubscriptions = (page, first): string[] => {
 		const jsonResponse = executeGqlQuery(
-			getHttpContext({ usePlatformAuth: true }),
+			getHttpContext({ usePlatformAuth }),
 			{
 				operationName: 'SUBSCRIPTIONS_QUERY',
 				variables: {
@@ -365,7 +361,7 @@ source.getUserSubscriptions = (): string[] => {
 				},
 				headers,
 				query: GET_USER_SUBSCRIPTIONS,
-				usePlatformAuth: true
+				usePlatformAuth
 			});
 
 		return (jsonResponse?.data?.me?.channel as Channel)?.followings?.edges?.map(edge => edge?.node?.creator?.name ?? "") ?? [];
@@ -383,7 +379,7 @@ source.getUserSubscriptions = (): string[] => {
 
 	do {
 		const response = fetchSubscriptions(page, first);
-
+		
 		items = response.map(creatorName => `${BASE_URL}/${creatorName}`);
 
 		subscriptions.push(...items);
@@ -411,7 +407,7 @@ source.getUserPlaylists = (): string[] => {
 		'X-DM-AppInfo-Type': X_DM_AppInfo_Type,
 		'X-DM-AppInfo-Version': X_DM_AppInfo_Version,
 		'X-DM-Neon-SSR': '0',
-		'X-DM-Preferred-Country': 'it',
+		'X-DM-Preferred-Country': getPreferredCountry(_settings?.preferredCountry),
 		Origin: BASE_URL,
 		DNT: '1',
 		Connection: 'keep-alive',
@@ -581,63 +577,6 @@ function searchPlaylists(contextQuery) {
 //Internals
 
 
-function getAnonymousUserTokenSingleton() {
-	// Check if the anonymous user token is available and not expired
-	if (AUTHORIZATION_TOKEN_ANONYMOUS_USER) {
-
-		const isTokenValid = AUTHORIZATION_TOKEN_ANONYMOUS_USER_EXPIRATION_DATE && new Date().getTime() < AUTHORIZATION_TOKEN_ANONYMOUS_USER_EXPIRATION_DATE;
-
-		if (isTokenValid) {
-			return AUTHORIZATION_TOKEN_ANONYMOUS_USER;
-		}
-	}
-
-	// Prepare the request body for obtaining a new token
-	const body = objectToUrlEncodedString({
-		client_id: CLIENT_ID,
-		client_secret: CLIENT_SECRET,
-		grant_type: 'client_credentials'
-	});
-
-	// Make the HTTP POST request to the authorization API
-	const res = httpClientRequestToken.POST(`${BASE_URL_API_AUTH}`, body, {
-		'User-Agent': USER_AGENT,
-		'Content-Type': 'application/x-www-form-urlencoded',
-		'Origin': BASE_URL,
-		'DNT': '1',
-		'Sec-GPC': '1',
-		'Connection': 'keep-alive',
-		'Sec-Fetch-Dest': 'empty',
-		'Sec-Fetch-Mode': 'cors',
-		'Sec-Fetch-Site': 'same-site',
-		'Priority': 'u=4',
-		'Pragma': 'no-cache',
-		'Cache-Control': 'no-cache'
-	}, false);
-
-	// Check if the response code indicates success
-	if (res.code !== 200) {
-		console.error('Failed to get token', res);
-		throw new ScriptException("", "Failed to get token: " + res.code + " - " + res.body);
-	}
-
-	// Parse the response JSON to extract the token information
-	const json = JSON.parse(res.body);
-
-	// Ensure the response contains the necessary token information
-	if (!json.token_type || !json.access_token) {
-		console.error('Invalid token response', res);
-		throw new ScriptException("", 'Invalid token response: ' + res.body);
-	}
-
-	// Store the token and its expiration date
-	AUTHORIZATION_TOKEN_ANONYMOUS_USER = `${json.token_type} ${json.access_token}`;
-	AUTHORIZATION_TOKEN_ANONYMOUS_USER_EXPIRATION_DATE = new Date().getTime() + (json.expires_in * 1000);
-
-	return AUTHORIZATION_TOKEN_ANONYMOUS_USER;
-}
-
-
 function getVideoPager(params, page) {
 
 	const count = ITEMS_PER_PAGE;
@@ -1162,54 +1101,4 @@ function getHttpContext(opts: { usePlatformAuth: Boolean } = { usePlatformAuth:
 	return opts.usePlatformAuth ? http : httpClientAnonymous;
 }
 
-function ensureDefaultSettings() {
-
-	if (!_settings) {
-		_settings = {};
-	}
-
-	if (_settings.hideSensitiveContent == undefined) {
-		_settings.hideSensitiveContent = true;
-	}
-
-	if (_settings.avatarSize == undefined) {
-		_settings.avatarSize = 8;
-	}
-
-	if (_settings.thumbnailResolution == undefined) {
-		_settings.thumbnailResolution = 7;
-	}
-
-	if (_settings.preferredCountry == undefined) {
-		const settingIndex = countryNames?.indexOf('');
-		_settings.preferredCountry = settingIndex;
-	}
-}
-
-function ensureInitHttpClients() {
-
-	try {
-		if (!httpClientRequestToken) {
-			httpClientRequestToken = http.newClient(false);
-			httpClientAnonymous = http.newClient(false);
-
-			const authorization = getAnonymousUserTokenSingleton();
-
-			httpClientAnonymous.setDefaultHeaders({ 'Authorization': authorization });
-
-		}
-	} catch (e) {
-		// log(e.message)
-	}
-}
-
-function ensureDefaults() {
-	ensureDefaultSettings();
-	ensureInitHttpClients();
-}
-
-//wip
-ensureDefaults();
-
-
 log("LOADED");
\ No newline at end of file
diff --git a/src/util.ts b/src/util.ts
index d28338fc4173b8067a1b89d73713a27668b68995..4dea800f887dfe6723f9829f33669baec43b4bb8 100644
--- a/src/util.ts
+++ b/src/util.ts
@@ -1,10 +1,17 @@
+let AUTHORIZATION_TOKEN_ANONYMOUS_USER: string = "";
+let AUTHORIZATION_TOKEN_ANONYMOUS_USER_EXPIRATION_DATE: number;
+let httpClientRequestToken: IHttp = http.newClient(false);
+
 import {
     BASE_URL,
     USER_AGENT,
     BASE_URL_API,
     X_DM_Preferred_Country,
     countryNames,
-    countryNamesToCode
+    countryNamesToCode,
+    CLIENT_ID,
+    CLIENT_SECRET,
+    BASE_URL_API_AUTH,
 } from './constants'
 
 export function getPreferredCountry(preferredCountryIndex) {
@@ -44,6 +51,63 @@ export function isUsernameUrl(url) {
 }
 
 
+export function getAnonymousUserTokenSingleton() {
+	// Check if the anonymous user token is available and not expired
+	if (AUTHORIZATION_TOKEN_ANONYMOUS_USER) {
+
+		const isTokenValid = AUTHORIZATION_TOKEN_ANONYMOUS_USER_EXPIRATION_DATE && new Date().getTime() < AUTHORIZATION_TOKEN_ANONYMOUS_USER_EXPIRATION_DATE;
+
+		if (isTokenValid) {
+			return AUTHORIZATION_TOKEN_ANONYMOUS_USER;
+		}
+	}
+
+	// Prepare the request body for obtaining a new token
+	const body = objectToUrlEncodedString({
+		client_id: CLIENT_ID,
+		client_secret: CLIENT_SECRET,
+		grant_type: 'client_credentials'
+	});
+
+	// Make the HTTP POST request to the authorization API
+	const res = httpClientRequestToken.POST(`${BASE_URL_API_AUTH}`, body, {
+		'User-Agent': USER_AGENT,
+		'Content-Type': 'application/x-www-form-urlencoded',
+		'Origin': BASE_URL,
+		'DNT': '1',
+		'Sec-GPC': '1',
+		'Connection': 'keep-alive',
+		'Sec-Fetch-Dest': 'empty',
+		'Sec-Fetch-Mode': 'cors',
+		'Sec-Fetch-Site': 'same-site',
+		'Priority': 'u=4',
+		'Pragma': 'no-cache',
+		'Cache-Control': 'no-cache'
+	}, false);
+
+	// Check if the response code indicates success
+	if (res.code !== 200) {
+		console.error('Failed to get token', res);
+		throw new ScriptException("", "Failed to get token: " + res.code + " - " + res.body);
+	}
+
+	// Parse the response JSON to extract the token information
+	const json = JSON.parse(res.body);
+
+	// Ensure the response contains the necessary token information
+	if (!json.token_type || !json.access_token) {
+		console.error('Invalid token response', res);
+		throw new ScriptException("", 'Invalid token response: ' + res.body);
+	}
+
+	// Store the token and its expiration date
+	AUTHORIZATION_TOKEN_ANONYMOUS_USER = `${json.token_type} ${json.access_token}`;
+	AUTHORIZATION_TOKEN_ANONYMOUS_USER_EXPIRATION_DATE = new Date().getTime() + (json.expires_in * 1000);
+
+	return AUTHORIZATION_TOKEN_ANONYMOUS_USER;
+}
+
+
 export function executeGqlQuery(httpClient, requestOptions) {
 
     const headersToAdd = requestOptions.headers || {
@@ -71,6 +135,10 @@ export function executeGqlQuery(httpClient, requestOptions) {
     const usePlatformAuth = requestOptions.usePlatformAuth == undefined ? false : requestOptions.usePlatformAuth;
     const throwOnError = requestOptions.throwOnError == undefined ? true : requestOptions.throwOnError;
 
+    if(!usePlatformAuth){
+        headersToAdd.Authorization =  getAnonymousUserTokenSingleton();
+    }
+
     const res = httpClient.POST(BASE_URL_API, gql, headersToAdd, usePlatformAuth);
 
     if (!res.isOk) {