diff --git a/DailymotionConfig.json b/DailymotionConfig.json
index e5db6b60a26ddbd511499b77a2cb748ccb55954c..c10cf6eec8ce479e8667a0f8afd1b657aa8d1672 100644
--- a/DailymotionConfig.json
+++ b/DailymotionConfig.json
@@ -16,6 +16,7 @@
     "Http"
   ],
   "allowEval": false,
+  "allowAllHttpHeaderAccess": true,
   "allowUrls": [
     "dailymotion.com",
     "www.dailymotion.com",
@@ -24,7 +25,8 @@
     "s1.dmcdn.net",
     "s2.dmcdn.net",
     "static1.dmcdn.net",
-    "static2.dmcdn.net"
+    "static2.dmcdn.net",
+    "api-2-0.spot.im"
   ],
   "authentication": {
     "loginUrl": "https://www.dailymotion.com/signin?urlback=/library",
diff --git a/build/DailymotionConfig.json b/build/DailymotionConfig.json
index e5db6b60a26ddbd511499b77a2cb748ccb55954c..c10cf6eec8ce479e8667a0f8afd1b657aa8d1672 100644
--- a/build/DailymotionConfig.json
+++ b/build/DailymotionConfig.json
@@ -16,6 +16,7 @@
     "Http"
   ],
   "allowEval": false,
+  "allowAllHttpHeaderAccess": true,
   "allowUrls": [
     "dailymotion.com",
     "www.dailymotion.com",
@@ -24,7 +25,8 @@
     "s1.dmcdn.net",
     "s2.dmcdn.net",
     "static1.dmcdn.net",
-    "static2.dmcdn.net"
+    "static2.dmcdn.net",
+    "api-2-0.spot.im"
   ],
   "authentication": {
     "loginUrl": "https://www.dailymotion.com/signin?urlback=/library",
diff --git a/build/DailymotionScript.js b/build/DailymotionScript.js
index e93155d4f0367807d7f0007061cabe2296700bf4..3b55d7d2aa9b598413783ab8651e607881ecf93d 100644
--- a/build/DailymotionScript.js
+++ b/build/DailymotionScript.js
@@ -2,6 +2,9 @@
 
 const BASE_URL = "https://www.dailymotion.com";
 const BASE_URL_API = "https://graphql.api.dailymotion.com";
+const BASE_URL_COMMENTS = "https://api-2-0.spot.im/v1.0.0/conversation/read";
+const BASE_URL_COMMENTS_AUTH = "https://api-2-0.spot.im/v1.0.0/authenticate";
+const BASE_URL_COMMENTS_THUMBNAILS = "https://images.spot.im/image/upload";
 const BASE_URL_API_AUTH = `${BASE_URL_API}/oauth/token`;
 const BASE_URL_VIDEO = `${BASE_URL}/video`;
 const BASE_URL_PLAYLIST = `${BASE_URL}/playlist`;
@@ -1765,7 +1768,8 @@ let config;
 let _settings;
 const state = {
     anonymousUserAuthorizationToken: "",
-    anonymousUserAuthorizationTokenExpirationDate: 0
+    anonymousUserAuthorizationTokenExpirationDate: 0,
+    messageServiceToken: ""
 };
 const LIKE_PLAYLIST_ID = "LIKE_PLAYLIST";
 const FAVORITES_PLAYLIST_ID = "FAVORITES_PLAYLIST";
@@ -1798,6 +1802,7 @@ source.enable = function (conf, settings, saveStateStr) {
             if (saveState) {
                 state.anonymousUserAuthorizationToken = saveState.anonymousUserAuthorizationToken;
                 state.anonymousUserAuthorizationTokenExpirationDate = saveState.anonymousUserAuthorizationTokenExpirationDate;
+                state.messageServiceToken = saveState.messageServiceToken;
                 if (!isTokenValid()) {
                     log("Token expired. Fetching a new one.");
                 }
@@ -1813,7 +1818,7 @@ source.enable = function (conf, settings, saveStateStr) {
         didSaveState = false;
     }
     if (!didSaveState) {
-        log("Getting a new token");
+        log("Getting a new tokens");
         const body = objectToUrlEncodedString({
             client_id: CLIENT_ID,
             client_secret: CLIENT_SECRET,
@@ -1844,8 +1849,28 @@ source.enable = function (conf, settings, saveStateStr) {
         }
         state.anonymousUserAuthorizationToken = `${json.token_type} ${json.access_token}`;
         state.anonymousUserAuthorizationTokenExpirationDate = Date.now() + (json.expires_in * 1000);
-        log(`json.expires_in: ${json.expires_in}`);
-        log(`state.anonymousUserAuthorizationTokenExpirationDate: ${state.anonymousUserAuthorizationTokenExpirationDate}`);
+        // get token for message service api-2-0.spot.im
+        const authenticateIm = http.POST(BASE_URL_COMMENTS_AUTH, "", {
+            'User-Agent': USER_AGENT,
+            Accept: '*/*',
+            'Accept-Language': 'en-US,en;q=0.5',
+            'x-spot-id': 'sp_vWPN1lBu',
+            'x-post-id': 'no$post',
+            'Content-Type': 'application/json',
+            'Origin': BASE_URL,
+            Connection: 'keep-alive',
+            Referer: BASE_URL,
+            'Sec-Fetch-Dest': 'empty',
+            'Sec-Fetch-Mode': 'cors',
+            'Sec-Fetch-Site': 'cross-site',
+            Priority: 'u=6',
+            'Content-Length': '0'
+        }, false);
+        if (!authenticateIm.isOk) {
+            // throw new UnavailableException('Failed to authenticate to comments service');
+            log('Failed to authenticate to comments service');
+        }
+        state.messageServiceToken = authenticateIm.headers["x-access-token"][0];
     }
 };
 source.getHome = function () {
@@ -1920,6 +1945,67 @@ source.getContentDetails = function (url) {
 source.saveState = () => {
     return JSON.stringify(state);
 };
+source.getSubComments = (comment) => {
+    const params = { "count": 5, "offset": 0, "parent_id": comment.context.id, "sort_by": "best", "child_count": comment.replyCount };
+    return getCommentPager(comment.contextUrl, params, 0);
+};
+source.getComments = (url) => {
+    const params = { "sort_by": "best", "offset": 0, "count": 10, "message_id": null, "depth": 2, "child_count": 2 };
+    return getCommentPager(url, params, 0);
+};
+function getCommentPager(url, params, page) {
+    try {
+        const xid = url.split('/').pop();
+        const commentsHeaders = {
+            'User-Agent': USER_AGENT,
+            Accept: 'application/json',
+            'Accept-Language': 'en-US,en;q=0.5',
+            'x-access-token': state.messageServiceToken,
+            'Content-Type': 'application/json',
+            'x-spot-id': 'sp_vWPN1lBu',
+            'x-post-id': xid,
+            'Origin': BASE_URL,
+            Connection: 'keep-alive',
+            Referer: BASE_URL,
+            'Sec-Fetch-Dest': 'empty',
+            'Sec-Fetch-Mode': 'cors',
+            'Sec-Fetch-Site': 'cross-site',
+            Priority: 'u=6',
+            TE: 'trailers'
+        };
+        const commentRequest = http.POST(BASE_URL_COMMENTS, JSON.stringify(params), commentsHeaders, false);
+        if (!commentRequest.isOk) {
+            throw new UnavailableException('Failed to authenticate to comments service');
+        }
+        const comments = JSON.parse(commentRequest.body);
+        const users = comments.conversation.users;
+        const results = comments.conversation.comments.map(v => {
+            const user = users[v.user_id];
+            return new Comment({
+                contextUrl: url,
+                author: new PlatformAuthorLink(new PlatformID(PLATFORM, user.id ?? "", config.id), user.display_name ?? "", "", `${BASE_URL_COMMENTS_THUMBNAILS}/${user.image_id}`),
+                message: v.content[0].text,
+                rating: new RatingLikes(v.stars),
+                date: v.written_at,
+                replyCount: v.total_replies_count ?? 0,
+                context: { id: v.id }
+            });
+        });
+        return new PlatformCommentPager(results, comments.conversation.has_next, url, params, ++page);
+    }
+    catch (error) {
+        bridge.log('Failed to get comments:' + error?.message);
+        return new PlatformCommentPager([], false, url, params, 0);
+    }
+}
+class PlatformCommentPager extends CommentPager {
+    constructor(results, hasMore, path, params, page) {
+        super(results, hasMore, { path, params, page });
+    }
+    nextPage() {
+        return getCommentPager(this.context.path, this.context.params, (this.context.page ?? 0) + 1);
+    }
+}
 //Playlist
 source.isPlaylistUrl = (url) => {
     return url.startsWith(BASE_URL_PLAYLIST) ||
diff --git a/src/DailymotionScript.ts b/src/DailymotionScript.ts
index 828edef7c9789b206b299b66242d9d6070cff233..bc571ad0366d2f938851f4fa862decd0bfadd491 100644
--- a/src/DailymotionScript.ts
+++ b/src/DailymotionScript.ts
@@ -3,7 +3,8 @@ let _settings: IDailymotionPluginSettings;
 
 const state = {
 	anonymousUserAuthorizationToken: "",
-	anonymousUserAuthorizationTokenExpirationDate: 0
+	anonymousUserAuthorizationTokenExpirationDate: 0,
+	messageServiceToken: ""
 };
 
 const LIKE_PLAYLIST_ID = "LIKE_PLAYLIST";
@@ -31,7 +32,11 @@ import {
 	PLAYLISTS_PER_PAGE_OPTIONS,
 	CLIENT_ID,
 	CLIENT_SECRET,
-	BASE_URL_API_AUTH
+	BASE_URL_API_AUTH,
+	PLATFORM,
+	BASE_URL_COMMENTS,
+	BASE_URL_COMMENTS_AUTH,
+	BASE_URL_COMMENTS_THUMBNAILS
 } from './constants';
 
 import {
@@ -122,16 +127,17 @@ source.enable = function (conf, settings, saveStateStr) {
 
 		config.id = "9c87e8db-e75d-48f4-afe5-2d203d4b95c5";
 	}
-
+	
 	let didSaveState = false;
-
+	
 	try {
 		if (saveStateStr) {
 			const saveState = JSON.parse(saveStateStr);
 			if (saveState) {
 				state.anonymousUserAuthorizationToken = saveState.anonymousUserAuthorizationToken;
 				state.anonymousUserAuthorizationTokenExpirationDate = saveState.anonymousUserAuthorizationTokenExpirationDate;
-
+				state.messageServiceToken = saveState.messageServiceToken;
+				
 				if (!isTokenValid()) {
 					log("Token expired. Fetching a new one.");
 				} else {
@@ -147,7 +153,7 @@ source.enable = function (conf, settings, saveStateStr) {
 
 	if (!didSaveState) {
 
-		log("Getting a new token");
+		log("Getting a new tokens");
 
 		const body = objectToUrlEncodedString({
 			client_id: CLIENT_ID,
@@ -185,8 +191,31 @@ source.enable = function (conf, settings, saveStateStr) {
 		state.anonymousUserAuthorizationToken = `${json.token_type} ${json.access_token}`;
 		state.anonymousUserAuthorizationTokenExpirationDate = Date.now() + (json.expires_in * 1000);
 
-		log(`json.expires_in: ${json.expires_in}`);
-		log(`state.anonymousUserAuthorizationTokenExpirationDate: ${state.anonymousUserAuthorizationTokenExpirationDate}`);
+
+		// get token for message service api-2-0.spot.im
+		const authenticateIm = http.POST(BASE_URL_COMMENTS_AUTH, "", {
+			'User-Agent': USER_AGENT,
+			Accept: '*/*',
+			'Accept-Language': 'en-US,en;q=0.5',
+			'x-spot-id': 'sp_vWPN1lBu',
+			'x-post-id': 'no$post',
+			'Content-Type': 'application/json',
+			'Origin': BASE_URL,
+			Connection: 'keep-alive',
+			Referer: BASE_URL,
+			'Sec-Fetch-Dest': 'empty',
+			'Sec-Fetch-Mode': 'cors',
+			'Sec-Fetch-Site': 'cross-site',
+			Priority: 'u=6',
+			'Content-Length': '0'
+		}, false);
+
+		if (!authenticateIm.isOk) {
+			// throw new UnavailableException('Failed to authenticate to comments service');
+			log('Failed to authenticate to comments service');
+		}
+
+		state.messageServiceToken = authenticateIm.headers["x-access-token"][0];
 	}
 
 }
@@ -295,6 +324,89 @@ source.saveState = () => {
 	return JSON.stringify(state);
 };
 
+source.getSubComments = (comment) => {
+	const params = { "count": 5, "offset": 0, "parent_id": comment.context.id, "sort_by": "best", "child_count": comment.replyCount };
+	return getCommentPager(comment.contextUrl, params, 0);
+}
+
+
+source.getComments = (url) => {
+	const params = { "sort_by": "best", "offset": 0, "count": 10, "message_id": null, "depth": 2, "child_count": 2 };
+	return getCommentPager(url, params, 0);
+}
+
+function getCommentPager(url, params, page) {
+
+	try {
+		const xid = url.split('/').pop();
+
+		const commentsHeaders = {
+			'User-Agent': USER_AGENT,
+			Accept: 'application/json',
+			'Accept-Language': 'en-US,en;q=0.5',
+			'x-access-token': state.messageServiceToken,
+			'Content-Type': 'application/json',
+			'x-spot-id': 'sp_vWPN1lBu',
+			'x-post-id': xid,
+			'Origin': BASE_URL,
+			Connection: 'keep-alive',
+			Referer: BASE_URL,
+			'Sec-Fetch-Dest': 'empty',
+			'Sec-Fetch-Mode': 'cors',
+			'Sec-Fetch-Site': 'cross-site',
+			Priority: 'u=6',
+			TE: 'trailers'
+		}
+
+		const commentRequest = http.POST(BASE_URL_COMMENTS, JSON.stringify(params), commentsHeaders, false);
+
+		if (!commentRequest.isOk) {
+			throw new UnavailableException('Failed to authenticate to comments service');
+		}
+
+		const comments = JSON.parse(commentRequest.body);
+
+		const users = comments.conversation.users;
+
+		const results = comments.conversation.comments.map(v => {
+
+			const user = users[v.user_id];
+
+			return new Comment({
+				contextUrl: url,
+				author: new PlatformAuthorLink(
+					new PlatformID(PLATFORM, user.id ?? "", config.id), 
+					user.display_name ?? "",
+					"",
+					`${BASE_URL_COMMENTS_THUMBNAILS}/${user.image_id}`
+				),
+				message: v.content[0].text,
+				rating: new RatingLikes(v.stars),
+				date: v.written_at,
+				replyCount: v.total_replies_count ?? 0,
+				context: { id: v.id }
+			});
+
+		});
+
+		return new PlatformCommentPager(results, comments.conversation.has_next, url, params, ++page);
+	} catch (error) {
+		bridge.log('Failed to get comments:' + error?.message);
+		return new PlatformCommentPager([], false, url, params, 0);
+	}
+
+}
+
+class PlatformCommentPager extends CommentPager {
+	constructor(results, hasMore, path, params, page) {
+		super(results, hasMore, { path, params, page });
+	}
+
+	nextPage() {
+		return getCommentPager(this.context.path, this.context.params, (this.context.page ?? 0) + 1);
+	}
+}
+
 //Playlist
 source.isPlaylistUrl = (url): boolean => {
 	return url.startsWith(BASE_URL_PLAYLIST) ||
diff --git a/src/constants.ts b/src/constants.ts
index 6d5f09708b0e5552970be03dcde5441cfc5636cc..44a65d15122d69e1783e29111f34b67cbf4cc19e 100644
--- a/src/constants.ts
+++ b/src/constants.ts
@@ -1,5 +1,8 @@
 export const BASE_URL = "https://www.dailymotion.com";
 export const BASE_URL_API = "https://graphql.api.dailymotion.com";
+export const BASE_URL_COMMENTS = "https://api-2-0.spot.im/v1.0.0/conversation/read";
+export const BASE_URL_COMMENTS_AUTH = "https://api-2-0.spot.im/v1.0.0/authenticate";
+export const BASE_URL_COMMENTS_THUMBNAILS = "https://images.spot.im/image/upload";
 export const BASE_URL_API_AUTH = `${BASE_URL_API}/oauth/token`;
 export const BASE_URL_VIDEO = `${BASE_URL}/video`;
 export const BASE_URL_PLAYLIST = `${BASE_URL}/playlist`;
diff --git a/types/plugin.d.ts b/types/plugin.d.ts
index 483d0693668b95756d309a927060d9e51a3eef73..48f40c3cc5e1943c58ddccebeb25e9be0159fe45 100644
--- a/types/plugin.d.ts
+++ b/types/plugin.d.ts
@@ -233,7 +233,7 @@ declare class PlatformComment {
     contextUrl: string;
     author: PlatformAuthorLink;
     message: string;
-    rating: any;
+    rating: IRating;
     date: number;
     replyCount: number;
     context: any;
@@ -1047,7 +1047,7 @@ declare class PlaylistPager {
 declare class CommentPager {
     context: any
 
-    constructor(results: PlatformVideo[], hasMore: boolean, context: any) {
+    constructor(results: PlatformComment[], hasMore: boolean, context: any) {
         this.plugin_type = "CommentPager";
         this.results = results ?? [];
         this.hasMore = hasMore ?? false;
@@ -1085,20 +1085,20 @@ interface Source {
     searchSuggestions(query: string): string[];
     search(query: string, type: string, order: string, filters: FilterGroup[]): VideoPager;
     getSearchCapabilities(): ResultCapabilities;
-    
+
     // Optional
     searchChannelVideos?(channelUrl: string, query: string, type: string, order: string, filters: FilterGroup[]): VideoPager;
     getSearchChannelVideoCapabilities?(): ResultCapabilities;
-    
+
     isChannelUrl(url: string): boolean;
     getChannel(url: string): PlatformChannel | null;
-    
+
     getChannelVideos(url: string, type: string, order: string, filters: FilterGroup[]): VideoPager;
     getChannelCapabilities(): ResultCapabilities;
     getSearchChannelContentsCapabilities(): ResultCapabilities;
     getPeekChannelTypes(): string[];
-    peekChannelContents (url, type): PlatformVideo[]
-    
+    peekChannelContents(url, type): PlatformVideo[]
+
     isVideoDetailsUrl(url: string): boolean;
     getVideoDetails(url: string): PlatformVideoDetails;
 
@@ -1125,6 +1125,10 @@ interface Source {
 
     getContentDetails(url: string): PlatformVideoDetails;
 
+    getComments(url: string): CommentPager;
+
+    getSubComments(comment: PlatformComment): CommentPager;
+
     getChannelPlaylists(url: string): PlaylistPager;
 
     searchChannelContents(channelUrl: string, query: string, type: string, order: string, filters: FilterGroup[]): VideoPager;
@@ -1431,7 +1435,7 @@ let http: IHttp
 
 
 interface IPager<T> {
-    hasMorePages() : Boolean;
+    hasMorePages(): Boolean;
     nextPage();
-    getResults() : List<T>;
+    getResults(): List<T>;
 }
\ No newline at end of file