diff --git a/src/CONST/index.ts b/src/CONST/index.ts
index cf0c6368090a..86f634120491 100755
--- a/src/CONST/index.ts
+++ b/src/CONST/index.ts
@@ -1335,6 +1335,7 @@ const CONST = {
                     REMOVE_FROM_ROOM: 'REMOVEFROMROOM',
                     LEAVE_ROOM: 'LEAVEROOM',
                     UPDATE_ROOM_DESCRIPTION: 'UPDATEROOMDESCRIPTION',
+                    UPDATE_ROOM_AVATAR: 'UPDATEROOMAVATAR',
                 },
                 REJECTEDTRANSACTION_THREAD: 'REJECTEDTRANSACTION_THREAD',
                 REJECTED_TRANSACTION_MARKASRESOLVED: 'REJECTEDTRANSACTIONMARKASRESOLVED',
diff --git a/src/components/AvatarButtonWithIcon.tsx b/src/components/AvatarButtonWithIcon.tsx
index d2800733d6ca..c99161469915 100644
--- a/src/components/AvatarButtonWithIcon.tsx
+++ b/src/components/AvatarButtonWithIcon.tsx
@@ -61,6 +61,9 @@ type AvatarButtonWithIconProps = {
 
     /** Optionally override the default "Edit" icon */
     editIcon?: IconAsset;
+
+    /** The name associated with avatar */
+    name?: string;
 };
 
 /**
@@ -82,6 +85,7 @@ function AvatarButtonWithIcon({
     disabled = false,
     editIcon = Expensicons.Pencil,
     anchorRef,
+    name = '',
 }: AvatarButtonWithIconProps) {
     const theme = useTheme();
     const styles = useThemeStyles();
@@ -110,6 +114,7 @@ function AvatarButtonWithIcon({
                             fallbackIcon={fallbackIcon}
                             size={size}
                             type={type}
+                            name={name}
                         />
                     ) : (
                         <DefaultAvatar />
diff --git a/src/components/AvatarWithImagePicker.tsx b/src/components/AvatarWithImagePicker.tsx
index 45bf6422ac7b..60914e47fdf1 100644
--- a/src/components/AvatarWithImagePicker.tsx
+++ b/src/components/AvatarWithImagePicker.tsx
@@ -69,6 +69,9 @@ type AvatarWithImagePickerProps = Omit<AvatarButtonWithIconProps, 'text' | 'onPr
 
     /** Allows to open an image without Attachment Picker. */
     enablePreview?: boolean;
+
+    /** The name associated with avatar */
+    name?: string;
 };
 
 const anchorAlignment = {horizontal: CONST.MODAL.ANCHOR_ORIGIN_HORIZONTAL.CENTER, vertical: CONST.MODAL.ANCHOR_ORIGIN_VERTICAL.TOP};
@@ -96,6 +99,7 @@ function AvatarWithImagePicker({
     onViewPhotoPress,
     enablePreview = false,
     editIcon = Expensicons.Pencil,
+    name = '',
 }: AvatarWithImagePickerProps) {
     const styles = useThemeStyles();
     const isFocused = useIsFocused();
@@ -263,6 +267,7 @@ function AvatarWithImagePicker({
                                         type={type}
                                         disabledStyle={disabledStyle}
                                         editIconStyle={editIconStyle}
+                                        name={name}
                                     />
                                 </OfflineWithFeedback>
                                 <PopoverMenu
diff --git a/src/components/RoomHeaderAvatars.tsx b/src/components/RoomHeaderAvatars.tsx
index e2c661526fb0..b8308ddd7720 100644
--- a/src/components/RoomHeaderAvatars.tsx
+++ b/src/components/RoomHeaderAvatars.tsx
@@ -1,25 +1,33 @@
 import React, {memo} from 'react';
 import {View} from 'react-native';
+import type {OnyxEntry} from 'react-native-onyx';
 import useStyleUtils from '@hooks/useStyleUtils';
 import useThemeStyles from '@hooks/useThemeStyles';
+import {clearAvatarErrors, getCurrentUserAccountID, updatePolicyRoomAvatar} from '@libs/actions/Report';
 import Navigation from '@libs/Navigation/Navigation';
+import {isUserCreatedPolicyRoom} from '@libs/ReportUtils';
+import {isDefaultAvatar} from '@libs/UserUtils';
 import CONST from '@src/CONST';
 import ROUTES from '@src/ROUTES';
+import type {Policy, Report} from '@src/types/onyx';
 import type {Icon} from '@src/types/onyx/OnyxCommon';
 import Avatar from './Avatar';
+import AvatarWithImagePicker from './AvatarWithImagePicker';
 import * as Expensicons from './Icon/Expensicons';
 import PressableWithoutFocus from './Pressable/PressableWithoutFocus';
 import Text from './Text';
 
 type RoomHeaderAvatarsProps = {
     icons: Icon[];
-    reportID: string;
+    report: Report;
+    policy: OnyxEntry<Policy>;
+    participants: number[];
 };
 
-function RoomHeaderAvatars({icons, reportID}: RoomHeaderAvatarsProps) {
+function RoomHeaderAvatars({icons, report, policy, participants}: RoomHeaderAvatarsProps) {
     const navigateToAvatarPage = (icon: Icon) => {
         if (icon.type === CONST.ICON_TYPE_WORKSPACE && icon.id) {
-            Navigation.navigate(ROUTES.REPORT_AVATAR.getRoute(reportID, icon.id.toString()));
+            Navigation.navigate(ROUTES.REPORT_AVATAR.getRoute(report?.reportID, icon.id.toString()));
             return;
         }
 
@@ -30,6 +38,8 @@ function RoomHeaderAvatars({icons, reportID}: RoomHeaderAvatarsProps) {
 
     const styles = useThemeStyles();
     const StyleUtils = useStyleUtils();
+    const currentUserAccountID = getCurrentUserAccountID();
+    const canEditRoomAvatar = isUserCreatedPolicyRoom(report) && participants.includes(currentUserAccountID) && !!policy && policy.role !== CONST.POLICY.ROLE.AUDITOR;
 
     if (!icons.length) {
         return null;
@@ -42,6 +52,31 @@ function RoomHeaderAvatars({icons, reportID}: RoomHeaderAvatarsProps) {
             return;
         }
 
+        if (canEditRoomAvatar) {
+            return (
+                <AvatarWithImagePicker
+                    source={icon.source || report.avatarUrl}
+                    avatarID={icon.id}
+                    isUsingDefaultAvatar={!report.avatarUrl || isDefaultAvatar(icon.source)}
+                    size={CONST.AVATAR_SIZE.X_LARGE}
+                    avatarStyle={[styles.avatarXLarge, styles.alignSelfCenter]}
+                    onViewPhotoPress={() => Navigation.navigate(ROUTES.REPORT_AVATAR.getRoute(report.reportID))}
+                    onImageRemoved={() => updatePolicyRoomAvatar(report.reportID)}
+                    onImageSelected={(file) => updatePolicyRoomAvatar(report.reportID, file)}
+                    editIcon={Expensicons.Camera}
+                    editIconStyle={styles.smallEditIconAccount}
+                    pendingAction={report.pendingFields?.avatar}
+                    errors={report.errorFields?.avatar ?? null}
+                    errorRowStyles={styles.mt6}
+                    onErrorClose={() => clearAvatarErrors(report.reportID)}
+                    style={[styles.w100, styles.mb3, styles.alignItemsStart, styles.sectionMenuItemTopDescription]}
+                    type={icon.type}
+                    editorMaskImage={Expensicons.ImageCropSquareMask}
+                    name={icon.name}
+                />
+            );
+        }
+
         return (
             <PressableWithoutFocus
                 style={styles.noOutline}
diff --git a/src/languages/de.ts b/src/languages/de.ts
index 2bd3f0d26878..0203e2e9b1d4 100644
--- a/src/languages/de.ts
+++ b/src/languages/de.ts
@@ -7145,6 +7145,8 @@ ${amount} für ${merchant} - ${date}`,
     roomChangeLog: {
         updateRoomDescription: 'setze die Raumbeschreibung auf:',
         clearRoomDescription: 'Raumbeschreibung gelöscht',
+        changedRoomAvatar: 'Hat das Raum-Avatar geändert',
+        removedRoomAvatar: 'Hat das Raum-Avatar entfernt',
     },
     delegate: {
         switchAccount: 'Konten wechseln:',
diff --git a/src/languages/en.ts b/src/languages/en.ts
index 445f97f58ef7..e6adc7b7c1ac 100755
--- a/src/languages/en.ts
+++ b/src/languages/en.ts
@@ -7094,6 +7094,8 @@ const translations = {
     roomChangeLog: {
         updateRoomDescription: 'set the room description to:',
         clearRoomDescription: 'cleared the room description',
+        changedRoomAvatar: 'changed the room avatar',
+        removedRoomAvatar: 'removed the room avatar',
     },
     delegate: {
         switchAccount: 'Switch accounts:',
diff --git a/src/languages/es.ts b/src/languages/es.ts
index 05f168b0369f..0a68a98750b4 100644
--- a/src/languages/es.ts
+++ b/src/languages/es.ts
@@ -7589,6 +7589,8 @@ ${amount} para ${merchant} - ${date}`,
     roomChangeLog: {
         updateRoomDescription: 'establece la descripción de la sala a:',
         clearRoomDescription: 'la descripción de la habitación ha sido borrada',
+        changedRoomAvatar: 'Cambió el avatar de la sala',
+        removedRoomAvatar: 'Eliminó el avatar de la sala',
     },
     delegate: {
         switchAccount: 'Cambiar de cuenta:',
diff --git a/src/languages/fr.ts b/src/languages/fr.ts
index 41041203c045..b4b9cf92229b 100644
--- a/src/languages/fr.ts
+++ b/src/languages/fr.ts
@@ -7148,6 +7148,8 @@ ${amount} pour ${merchant} - ${date}`,
     roomChangeLog: {
         updateRoomDescription: 'définir la description de la salle sur :',
         clearRoomDescription: 'effacé la description de la salle',
+        changedRoomAvatar: 'A changé l’avatar de la salle',
+        removedRoomAvatar: 'A supprimé l’avatar de la salle',
     },
     delegate: {
         switchAccount: 'Changer de compte :',
diff --git a/src/languages/it.ts b/src/languages/it.ts
index 947068e6ac30..2b0b16753ae8 100644
--- a/src/languages/it.ts
+++ b/src/languages/it.ts
@@ -7153,6 +7153,8 @@ ${amount} per ${merchant} - ${date}`,
     roomChangeLog: {
         updateRoomDescription: 'imposta la descrizione della stanza su:',
         clearRoomDescription: 'cancellato la descrizione della stanza',
+        changedRoomAvatar: "Ha cambiato l'avatar della stanza",
+        removedRoomAvatar: "Ha rimosso l'avatar della stanza",
     },
     delegate: {
         switchAccount: 'Cambia account:',
diff --git a/src/languages/ja.ts b/src/languages/ja.ts
index b21529a4a43d..bc5dd4aa22db 100644
--- a/src/languages/ja.ts
+++ b/src/languages/ja.ts
@@ -7082,6 +7082,8 @@ ${date} - ${merchant}に${amount}`,
     roomChangeLog: {
         updateRoomDescription: '部屋の説明を次のように設定します：',
         clearRoomDescription: '部屋の説明をクリアしました',
+        changedRoomAvatar: 'ルームのアバターを変更しました',
+        removedRoomAvatar: 'ルームのアバターを削除しました',
     },
     delegate: {
         switchAccount: 'アカウントを切り替える:',
diff --git a/src/languages/nl.ts b/src/languages/nl.ts
index 04dbe1ef57e8..fefb5971ee2b 100644
--- a/src/languages/nl.ts
+++ b/src/languages/nl.ts
@@ -7135,6 +7135,8 @@ ${amount} voor ${merchant} - ${date}`,
     roomChangeLog: {
         updateRoomDescription: 'stel de kamerbeschrijving in op:',
         clearRoomDescription: 'de kamerbeschrijving gewist',
+        changedRoomAvatar: 'De avatar van de kamer is gewijzigd',
+        removedRoomAvatar: 'De avatar van de kamer is verwijderd',
     },
     delegate: {
         switchAccount: 'Accounts wisselen:',
diff --git a/src/languages/pl.ts b/src/languages/pl.ts
index 9699057292ec..d92b7223ae1e 100644
--- a/src/languages/pl.ts
+++ b/src/languages/pl.ts
@@ -7123,6 +7123,8 @@ ${amount} dla ${merchant} - ${date}`,
     roomChangeLog: {
         updateRoomDescription: 'ustaw opis pokoju na:',
         clearRoomDescription: 'wyczyszczono opis pokoju',
+        changedRoomAvatar: 'Zmieniono awatar pokoju',
+        removedRoomAvatar: 'Usunięto awatar pokoju',
     },
     delegate: {
         switchAccount: 'Przełącz konta:',
diff --git a/src/languages/pt-BR.ts b/src/languages/pt-BR.ts
index 7050ce68dc56..602e893bd8ef 100644
--- a/src/languages/pt-BR.ts
+++ b/src/languages/pt-BR.ts
@@ -7130,6 +7130,8 @@ ${amount} para ${merchant} - ${date}`,
     roomChangeLog: {
         updateRoomDescription: 'defina a descrição da sala para:',
         clearRoomDescription: 'limpou a descrição da sala',
+        changedRoomAvatar: 'Alterou o avatar da sala',
+        removedRoomAvatar: 'Removeu o avatar da sala',
     },
     delegate: {
         switchAccount: 'Alternar contas:',
diff --git a/src/languages/zh-hans.ts b/src/languages/zh-hans.ts
index 2db0379d1000..8af25e6010ef 100644
--- a/src/languages/zh-hans.ts
+++ b/src/languages/zh-hans.ts
@@ -6985,6 +6985,8 @@ ${merchant}的${amount} - ${date}`,
     roomChangeLog: {
         updateRoomDescription: '将房间描述设置为：',
         clearRoomDescription: '清除了房间描述',
+        changedRoomAvatar: '更改了房间头像',
+        removedRoomAvatar: '移除了房间头像',
     },
     delegate: {
         switchAccount: '切换账户：',
diff --git a/src/libs/API/parameters/UpdateRoomAvatarParams.ts b/src/libs/API/parameters/UpdateRoomAvatarParams.ts
new file mode 100644
index 000000000000..889d13e3d80d
--- /dev/null
+++ b/src/libs/API/parameters/UpdateRoomAvatarParams.ts
@@ -0,0 +1,9 @@
+import type {CustomRNImageManipulatorResult} from '@libs/cropOrRotateImage/types';
+
+type UpdateRoomAvatarParams = {
+    reportID: string;
+    file: File | CustomRNImageManipulatorResult | undefined;
+    reportActionID: string;
+};
+
+export default UpdateRoomAvatarParams;
diff --git a/src/libs/API/parameters/index.ts b/src/libs/API/parameters/index.ts
index 694ff0430b8b..e1f7fb3a1c4d 100644
--- a/src/libs/API/parameters/index.ts
+++ b/src/libs/API/parameters/index.ts
@@ -104,6 +104,7 @@ export type {default as UpdateStatusParams} from './UpdateStatusParams';
 export type {default as UpdateThemeParams} from './UpdateThemeParams';
 export type {default as UpdateUserAvatarParams} from './UpdateUserAvatarParams';
 export type {default as UpdateGroupChatAvatarParams} from './UpdateGroupChatAvatarParams';
+export type {default as UpdateRoomAvatarParams} from './UpdateRoomAvatarParams';
 export type {default as ValidateBankAccountWithTransactionsParams} from './ValidateBankAccountWithTransactionsParams';
 export type {default as ValidateLoginParams} from './ValidateLoginParams';
 export type {default as ValidateSecondaryLoginParams} from './ValidateSecondaryLoginParams';
diff --git a/src/libs/API/types.ts b/src/libs/API/types.ts
index c65d2d2ad017..e3ea06cb6cfa 100644
--- a/src/libs/API/types.ts
+++ b/src/libs/API/types.ts
@@ -71,6 +71,7 @@ const WRITE_COMMANDS = {
     UPDATE_SELECTED_TIMEZONE: 'UpdateSelectedTimezone',
     UPDATE_USER_AVATAR: 'UpdateUserAvatar',
     UPDATE_GROUP_CHAT_AVATAR: 'UpdateGroupChatAvatar',
+    UPDATE_ROOM_AVATAR: 'UpdateRoomAvatar',
     DELETE_USER_AVATAR: 'DeleteUserAvatar',
     REFER_TEACHERS_UNITE_VOLUNTEER: 'ReferTeachersUniteVolunteer',
     ADD_SCHOOL_PRINCIPAL: 'AddSchoolPrincipal',
@@ -632,6 +633,7 @@ type WriteCommandParameters = {
     [WRITE_COMMANDS.INVITE_TO_ROOM]: Parameters.InviteToRoomParams;
     [WRITE_COMMANDS.INVITE_TO_GROUP_CHAT]: Parameters.InviteToGroupChatParams;
     [WRITE_COMMANDS.UPDATE_GROUP_CHAT_AVATAR]: Parameters.UpdateGroupChatAvatarParams;
+    [WRITE_COMMANDS.UPDATE_ROOM_AVATAR]: Parameters.UpdateRoomAvatarParams;
     [WRITE_COMMANDS.PUSHER_PING]: Parameters.PusherPingParams;
     [WRITE_COMMANDS.LEAVE_GROUP_CHAT]: Parameters.LeaveGroupChatParams;
     [WRITE_COMMANDS.REMOVE_FROM_GROUP_CHAT]: Parameters.RemoveFromGroupChatParams;
diff --git a/src/libs/OptionsListUtils/index.ts b/src/libs/OptionsListUtils/index.ts
index c22c12fa3ffb..4a02b6c33622 100644
--- a/src/libs/OptionsListUtils/index.ts
+++ b/src/libs/OptionsListUtils/index.ts
@@ -51,6 +51,7 @@ import {
     getReportActionHtml,
     getReportActionMessageText,
     getRetractedMessage,
+    getRoomAvatarUpdatedMessage,
     getRoomChangeLogMessage,
     getSortedReportActions,
     getTravelUpdateMessage,
@@ -764,6 +765,8 @@ function getLastMessageTextForReport({
         lastMessageTextFromReport = translateLocal('violations.resolvedDuplicates');
     } else if (isActionOfType(lastReportAction, CONST.REPORT.ACTIONS.TYPE.ROOM_CHANGE_LOG.UPDATE_ROOM_DESCRIPTION)) {
         lastMessageTextFromReport = getUpdateRoomDescriptionMessage(lastReportAction);
+    } else if (isActionOfType(lastReportAction, CONST.REPORT.ACTIONS.TYPE.ROOM_CHANGE_LOG.UPDATE_ROOM_AVATAR)) {
+        lastMessageTextFromReport = getRoomAvatarUpdatedMessage(lastReportAction);
     } else if (isActionOfType(lastReportAction, CONST.REPORT.ACTIONS.TYPE.RETRACTED)) {
         lastMessageTextFromReport = getRetractedMessage();
     } else if (isActionOfType(lastReportAction, CONST.REPORT.ACTIONS.TYPE.REOPENED)) {
diff --git a/src/libs/ReportActionsUtils.ts b/src/libs/ReportActionsUtils.ts
index e82026942aee..5b1e940e3446 100644
--- a/src/libs/ReportActionsUtils.ts
+++ b/src/libs/ReportActionsUtils.ts
@@ -1905,6 +1905,11 @@ function getReportActionMessageFragments(action: ReportAction): Message[] {
         return [{text: message, html: `<muted-text>${message}</muted-text>`, type: 'COMMENT'}];
     }
 
+    if (isActionOfType(action, CONST.REPORT.ACTIONS.TYPE.ROOM_CHANGE_LOG.UPDATE_ROOM_AVATAR)) {
+        const message = getRoomAvatarUpdatedMessage(action);
+        return [{text: message, html: `<muted-text>${message}</muted-text>`, type: 'COMMENT'}];
+    }
+
     if (isActionOfType(action, CONST.REPORT.ACTIONS.TYPE.POLICY_CHANGE_LOG.UPDATE_DESCRIPTION)) {
         const message = getWorkspaceDescriptionUpdatedMessage(action);
         return [{text: message, html: `<muted-text>${message}</muted-text>`, type: 'COMMENT'}];
@@ -2262,6 +2267,17 @@ function getUpdateRoomDescriptionMessage(reportAction: ReportAction): string {
     return translateLocal('roomChangeLog.clearRoomDescription');
 }
 
+function getRoomAvatarUpdatedMessage(reportAction: ReportAction): string {
+    const originalMessage = getOriginalMessage(reportAction) as OriginalMessageChangeLog;
+    if (originalMessage?.avatarURL) {
+        // eslint-disable-next-line @typescript-eslint/no-deprecated
+        return translateLocal('roomChangeLog.changedRoomAvatar');
+    }
+
+    // eslint-disable-next-line @typescript-eslint/no-deprecated
+    return translateLocal('roomChangeLog.removedRoomAvatar');
+}
+
 function getRetractedMessage(): string {
     // eslint-disable-next-line @typescript-eslint/no-deprecated
     return translateLocal('iou.retracted');
@@ -3406,6 +3422,7 @@ export {
     getExportIntegrationLastMessageText,
     getExportIntegrationMessageHTML,
     getUpdateRoomDescriptionMessage,
+    getRoomAvatarUpdatedMessage,
     didMessageMentionCurrentUser,
     getPolicyChangeLogAddEmployeeMessage,
     getPolicyChangeLogUpdateEmployee,
diff --git a/src/libs/ReportUtils.ts b/src/libs/ReportUtils.ts
index a6c1449c6b73..d5583e4ede62 100644
--- a/src/libs/ReportUtils.ts
+++ b/src/libs/ReportUtils.ts
@@ -570,6 +570,11 @@ type OptimisticRoomDescriptionUpdatedReportAction = Pick<
     'actorAccountID' | 'created' | 'message' | 'person' | 'reportActionID' | 'pendingAction' | 'actionName' | 'originalMessage'
 >;
 
+type OptimisticRoomAvatarUpdatedReportAction = Pick<
+    ReportAction<typeof CONST.REPORT.ACTIONS.TYPE.ROOM_CHANGE_LOG.UPDATE_ROOM_AVATAR>,
+    'actorAccountID' | 'created' | 'message' | 'person' | 'reportActionID' | 'pendingAction' | 'actionName' | 'originalMessage'
+>;
+
 type OptimisticChatReport = Pick<
     Report,
     | 'type'
@@ -1004,6 +1009,7 @@ Onyx.connect({
                 return acc;
             }
 
+            // eslint-disable-next-line @typescript-eslint/no-deprecated
             InteractionManager.runAfterInteractions(() => {
                 handlePreexistingReport(report);
             });
@@ -3530,6 +3536,26 @@ function getIconsForInvoiceReport(
     return icons;
 }
 
+/**
+ * Helper function to get the icons for a user-created policy room. Only to be used in getIcons().
+ */
+function getIconsForUserCreatedPolicyRoom(report: OnyxInputOrEntry<Report>, policy: OnyxInputOrEntry<Policy>): Icon[] {
+    if (!report) {
+        return [];
+    }
+    if (report?.avatarUrl) {
+        return [
+            {
+                source: report.avatarUrl,
+                type: CONST.ICON_TYPE_WORKSPACE,
+                name: getPolicyName({report, policy}),
+                id: report?.policyID,
+            },
+        ];
+    }
+    return [getWorkspaceIcon(report, policy)];
+}
+
 /**
  * Returns the appropriate icons for the given chat report using the stored personalDetails.
  * The Avatar sources can be URLs or Icon components according to the chat type.
@@ -3566,6 +3592,9 @@ function getIcons(
     if (isDomainRoom(report)) {
         return getIconsForDomainRoom(report);
     }
+    if (isUserCreatedPolicyRoom(report)) {
+        return getIconsForUserCreatedPolicyRoom(report, policy);
+    }
     if (isAdminRoom(report) || isAnnounceRoom(report) || isChatRoom(report) || (isArchivedNonExpenseReport(report, isReportArchived) && !chatIncludesConcierge(report))) {
         return getIconsForPolicyRoom(report, personalDetails, policy, invoiceReceiverPolicy);
     }
@@ -7685,6 +7714,38 @@ function buildOptimisticRoomDescriptionUpdatedReportAction(description: string):
     };
 }
 
+/**
+ * Returns the necessary reportAction onyx data to indicate that the room avatar has been updated
+ */
+function buildOptimisticRoomAvatarUpdatedReportAction(avatarURL: string): OptimisticRoomAvatarUpdatedReportAction {
+    const now = DateUtils.getDBTime();
+    return {
+        reportActionID: rand64(),
+        actionName: CONST.REPORT.ACTIONS.TYPE.ROOM_CHANGE_LOG.UPDATE_ROOM_AVATAR,
+        pendingAction: CONST.RED_BRICK_ROAD_PENDING_ACTION.ADD,
+        actorAccountID: currentUserAccountID,
+        message: [
+            {
+                type: CONST.REPORT.MESSAGE.TYPE.COMMENT,
+                text: avatarURL ? `changed the room avatar` : 'removed the room avatar',
+                html: avatarURL ? `<muted-text>changed the room avatar</muted-text>` : '<muted-text>removed the room avatar</muted-text>',
+            },
+        ],
+        person: [
+            {
+                type: CONST.REPORT.MESSAGE.TYPE.TEXT,
+                style: 'strong',
+                text: getCurrentUserDisplayNameOrEmail(),
+            },
+        ],
+        originalMessage: {
+            avatarURL,
+            lastModified: now,
+        },
+        created: now,
+    };
+}
+
 /**
  * Returns the necessary reportAction onyx data to indicate that the transaction has been put on hold optimistically
  * @param [created] - Action created time
@@ -12223,6 +12284,7 @@ export {
     buildOptimisticChangePolicyReportAction,
     buildOptimisticRenamedRoomReportAction,
     buildOptimisticRoomDescriptionUpdatedReportAction,
+    buildOptimisticRoomAvatarUpdatedReportAction,
     buildOptimisticReportPreview,
     buildOptimisticActionableTrackExpenseWhisper,
     buildOptimisticSubmittedReportAction,
diff --git a/src/libs/SidebarUtils.ts b/src/libs/SidebarUtils.ts
index 2ffe5bf060cd..44198e6fecc6 100644
--- a/src/libs/SidebarUtils.ts
+++ b/src/libs/SidebarUtils.ts
@@ -52,6 +52,7 @@ import {
     getReportAction,
     getReportActionMessageText,
     getRetractedMessage,
+    getRoomAvatarUpdatedMessage,
     getTagListNameUpdatedMessage,
     getTravelUpdateMessage,
     getUpdatedApprovalRuleMessage,
@@ -896,6 +897,8 @@ function getOptionData({
             result.alternateText = getMessageOfOldDotReportAction(lastAction);
         } else if (lastAction?.actionName === CONST.REPORT.ACTIONS.TYPE.ROOM_CHANGE_LOG.UPDATE_ROOM_DESCRIPTION) {
             result.alternateText = getUpdateRoomDescriptionMessage(lastAction);
+        } else if (lastAction?.actionName === CONST.REPORT.ACTIONS.TYPE.ROOM_CHANGE_LOG.UPDATE_ROOM_AVATAR) {
+            result.alternateText = getRoomAvatarUpdatedMessage(lastAction);
         } else if (lastAction?.actionName === CONST.REPORT.ACTIONS.TYPE.POLICY_CHANGE_LOG.ADD_EMPLOYEE) {
             result.alternateText = getPolicyChangeLogAddEmployeeMessage(lastAction);
         } else if (lastAction?.actionName === CONST.REPORT.ACTIONS.TYPE.POLICY_CHANGE_LOG.UPDATE_EMPLOYEE) {
diff --git a/src/libs/actions/Report.ts b/src/libs/actions/Report.ts
index 4608f1257d18..0414953ff417 100644
--- a/src/libs/actions/Report.ts
+++ b/src/libs/actions/Report.ts
@@ -54,6 +54,7 @@ import type {
     UpdateReportNotificationPreferenceParams,
     UpdateReportPrivateNoteParams,
     UpdateReportWriteCapabilityParams,
+    UpdateRoomAvatarParams,
     UpdateRoomDescriptionParams,
 } from '@libs/API/parameters';
 import type ExportReportCSVParams from '@libs/API/parameters/ExportReportCSVParams';
@@ -111,6 +112,7 @@ import {
     buildOptimisticMovedReportAction,
     buildOptimisticRenamedRoomReportAction,
     buildOptimisticReportPreview,
+    buildOptimisticRoomAvatarUpdatedReportAction,
     buildOptimisticRoomDescriptionUpdatedReportAction,
     buildOptimisticSelfDMReport,
     buildOptimisticUnHoldReportAction,
@@ -924,7 +926,15 @@ function updateChatName(reportID: string, reportName: string, type: typeof CONST
     API.write(command, parameters, {optimisticData, successData, failureData});
 }
 
-function updateGroupChatAvatar(reportID: string, file?: File | CustomRNImageManipulatorResult) {
+/**
+ * Helper function to build optimistic, success, and failure Onyx updates
+ * when updating or removing a report's avatar.
+ *
+ * @param reportID - The report ID of the policy room.
+ * @param [file] - (Optional) The selected image file to update the avatar with.
+ * If not provided, the existing avatar will be removed.
+ */
+function buildUpdateReportAvatarOnyxData(reportID: string, file?: File | CustomRNImageManipulatorResult) {
     // If we have no file that means we are removing the avatar.
     const optimisticData: OnyxUpdate[] = [
         {
@@ -967,10 +977,67 @@ function updateGroupChatAvatar(reportID: string, file?: File | CustomRNImageMani
             },
         },
     ];
+
+    return {optimisticData, successData, failureData};
+}
+
+/**
+ * Updates the avatar for a group chat.
+ */
+function updateGroupChatAvatar(reportID: string, file?: File | CustomRNImageManipulatorResult) {
+    const {optimisticData, successData, failureData} = buildUpdateReportAvatarOnyxData(reportID, file);
     const parameters: UpdateGroupChatAvatarParams = {file, reportID};
     API.write(WRITE_COMMANDS.UPDATE_GROUP_CHAT_AVATAR, parameters, {optimisticData, failureData, successData});
 }
 
+/**
+ * Updates the avatar for a policy room.
+ */
+function updatePolicyRoomAvatar(reportID: string, file?: File | CustomRNImageManipulatorResult) {
+    const avatarURL = file?.uri ?? '';
+    const {optimisticData, successData, failureData} = buildUpdateReportAvatarOnyxData(reportID, file);
+
+    const optimisticAction = buildOptimisticRoomAvatarUpdatedReportAction(avatarURL);
+    optimisticData.push({
+        onyxMethod: Onyx.METHOD.MERGE,
+        key: `${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${reportID}`,
+        value: {[optimisticAction.reportActionID]: optimisticAction},
+    });
+
+    // Update the report with last action details
+    optimisticData.push({
+        onyxMethod: Onyx.METHOD.MERGE,
+        key: `${ONYXKEYS.COLLECTION.REPORT}${reportID}`,
+        value: {
+            lastActorAccountID: currentUserAccountID,
+            lastVisibleActionCreated: optimisticAction.created,
+            lastMessageText: (optimisticAction.message as Message[]).at(0)?.text,
+        },
+    });
+
+    // Add success data to clear pending action
+    successData.push({
+        onyxMethod: Onyx.METHOD.MERGE,
+        key: `${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${reportID}`,
+        value: {
+            [optimisticAction.reportActionID]: {pendingAction: null},
+        },
+    });
+
+    failureData.push({
+        onyxMethod: Onyx.METHOD.MERGE,
+        key: `${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${reportID}`,
+        value: {
+            [optimisticAction.reportActionID]: {
+                pendingAction: null,
+            },
+        },
+    });
+
+    const parameters: UpdateRoomAvatarParams = {reportID, file, reportActionID: optimisticAction.reportActionID};
+    API.write(WRITE_COMMANDS.UPDATE_ROOM_AVATAR, parameters, {optimisticData, failureData, successData});
+}
+
 /**
  * Clear error and pending fields for the report avatar
  */
@@ -6222,6 +6289,7 @@ export {
     unsubscribeFromReportChannel,
     updateDescription,
     updateGroupChatAvatar,
+    updatePolicyRoomAvatar,
     updateGroupChatMemberRoles,
     updateChatName,
     updateLastVisitTime,
diff --git a/src/pages/ReportDetailsPage.tsx b/src/pages/ReportDetailsPage.tsx
index d84ff052ee21..f9e30c166e6d 100644
--- a/src/pages/ReportDetailsPage.tsx
+++ b/src/pages/ReportDetailsPage.tsx
@@ -19,6 +19,7 @@ import PressableWithoutFeedback from '@components/Pressable/PressableWithoutFeed
 import type {PromotedAction} from '@components/PromotedActionsBar';
 import PromotedActionsBar, {PromotedActions} from '@components/PromotedActionsBar';
 import ReportActionAvatars from '@components/ReportActionAvatars';
+import RoomHeaderAvatars from '@components/RoomHeaderAvatars';
 import ScreenWrapper from '@components/ScreenWrapper';
 import ScrollView from '@components/ScrollView';
 import {useSearchContext} from '@components/Search/SearchContext';
@@ -591,6 +592,18 @@ function ReportDetailsPage({policy, report, route, reportMetadata}: ReportDetail
     ) : null;
 
     const renderedAvatar = useMemo(() => {
+        if (isChatRoom && !isThread) {
+            return (
+                <View style={styles.mb3}>
+                    <RoomHeaderAvatars
+                        icons={icons}
+                        report={report}
+                        policy={policy}
+                        participants={participants}
+                    />
+                </View>
+            );
+        }
         if (!isGroupChat || isThread) {
             return (
                 <View style={styles.mb3}>
@@ -627,21 +640,7 @@ function ReportDetailsPage({policy, report, route, reportMetadata}: ReportDetail
                 style={[styles.w100, styles.mb3]}
             />
         );
-    }, [
-        isGroupChat,
-        isThread,
-        icons,
-        report.avatarUrl,
-        report.pendingFields?.avatar,
-        report.errorFields?.avatar,
-        report.reportID,
-        styles.avatarXLarge,
-        styles.smallEditIconAccount,
-        styles.mt6,
-        styles.w100,
-        styles.mb3,
-        moneyRequestReport,
-    ]);
+    }, [isGroupChat, isThread, isChatRoom, icons, report, styles.avatarXLarge, styles.smallEditIconAccount, styles.mt6, styles.w100, styles.mb3, moneyRequestReport?.reportID]);
 
     const canJoin = canJoinChat(report, parentReportAction, policy, !!reportNameValuePairs?.private_isArchived);
 
diff --git a/src/pages/home/report/ContextMenu/ContextMenuActions.tsx b/src/pages/home/report/ContextMenu/ContextMenuActions.tsx
index 9c82262e6aba..df4ee4f59f6c 100644
--- a/src/pages/home/report/ContextMenu/ContextMenuActions.tsx
+++ b/src/pages/home/report/ContextMenu/ContextMenuActions.tsx
@@ -50,6 +50,7 @@ import {
     getRenamedAction,
     getReopenedMessage,
     getReportActionMessageText,
+    getRoomAvatarUpdatedMessage,
     getTagListNameUpdatedMessage,
     getTravelUpdateMessage,
     getUpdatedApprovalRuleMessage,
@@ -683,6 +684,8 @@ const ContextMenuActions: ContextMenuAction[] = [
                     setClipboardMessage(getExportIntegrationMessageHTML(reportAction));
                 } else if (reportAction?.actionName === CONST.REPORT.ACTIONS.TYPE.ROOM_CHANGE_LOG.UPDATE_ROOM_DESCRIPTION) {
                     setClipboardMessage(getUpdateRoomDescriptionMessage(reportAction));
+                } else if (reportAction?.actionName === CONST.REPORT.ACTIONS.TYPE.ROOM_CHANGE_LOG.UPDATE_ROOM_AVATAR) {
+                    setClipboardMessage(getRoomAvatarUpdatedMessage(reportAction));
                 } else if (reportAction?.actionName === CONST.REPORT.ACTIONS.TYPE.POLICY_CHANGE_LOG.ADD_EMPLOYEE) {
                     setClipboardMessage(getPolicyChangeLogAddEmployeeMessage(reportAction));
                 } else if (reportAction?.actionName === CONST.REPORT.ACTIONS.TYPE.POLICY_CHANGE_LOG.UPDATE_EMPLOYEE) {
diff --git a/src/pages/media/AttachmentModalScreen/routes/report/ReportAvatarModalContent.tsx b/src/pages/media/AttachmentModalScreen/routes/report/ReportAvatarModalContent.tsx
index dd8e21db0aeb..ae5ed59d621c 100644
--- a/src/pages/media/AttachmentModalScreen/routes/report/ReportAvatarModalContent.tsx
+++ b/src/pages/media/AttachmentModalScreen/routes/report/ReportAvatarModalContent.tsx
@@ -1,6 +1,6 @@
 import React, {useMemo} from 'react';
 import useOnyx from '@hooks/useOnyx';
-import {getDefaultGroupAvatar, getPolicyName, getReportName, getWorkspaceIcon, isGroupChat, isThread} from '@libs/ReportUtils';
+import {getDefaultGroupAvatar, getPolicyName, getReportName, getWorkspaceIcon, isGroupChat, isThread, isUserCreatedPolicyRoom} from '@libs/ReportUtils';
 import {getFullSizeAvatar} from '@libs/UserUtils';
 import type {AttachmentModalBaseContentProps} from '@pages/media/AttachmentModalScreen/AttachmentModalBaseContent/types';
 import AttachmentModalContainer from '@pages/media/AttachmentModalScreen/AttachmentModalContainer';
@@ -24,6 +24,13 @@ function ReportAvatarModalContent({navigation, route}: AttachmentModalScreenProp
                 isWorkspaceAvatar: false,
             };
         }
+        if (isUserCreatedPolicyRoom(report)) {
+            return {
+                source: report?.avatarUrl ? getFullSizeAvatar(report.avatarUrl, 0) : undefined,
+                headerTitle: getReportName(report),
+                isWorkspaceAvatar: false,
+            };
+        }
 
         return {
             source: getFullSizeAvatar(getWorkspaceIcon(report, policy).source, 0),
diff --git a/src/pages/workspace/WorkspaceOverviewPage.tsx b/src/pages/workspace/WorkspaceOverviewPage.tsx
index 161b486a7179..3296438a3465 100644
--- a/src/pages/workspace/WorkspaceOverviewPage.tsx
+++ b/src/pages/workspace/WorkspaceOverviewPage.tsx
@@ -386,6 +386,7 @@ function WorkspaceOverviewPage({policyDraft, policy: policyProp, route}: Workspa
                             source={policy?.avatarURL ?? ''}
                             avatarID={policy?.id}
                             size={CONST.AVATAR_SIZE.X_LARGE}
+                            name={policyName}
                             avatarStyle={styles.avatarXLarge}
                             enablePreview
                             DefaultAvatar={DefaultAvatar}
diff --git a/src/types/onyx/OriginalMessage.ts b/src/types/onyx/OriginalMessage.ts
index 8751b4c420d5..e86af9b86791 100644
--- a/src/types/onyx/OriginalMessage.ts
+++ b/src/types/onyx/OriginalMessage.ts
@@ -367,6 +367,9 @@ type OriginalMessageChangeLog = {
 
     /** Name of the added category */
     categoryName?: string;
+
+    /** Avatar URL of workspace room */
+    avatarURL?: string;
 };
 
 /** Model of change log */
diff --git a/tests/actions/EnforceActionExportRestrictions.ts b/tests/actions/EnforceActionExportRestrictions.ts
index be76cb9f5b02..5c467834715d 100644
--- a/tests/actions/EnforceActionExportRestrictions.ts
+++ b/tests/actions/EnforceActionExportRestrictions.ts
@@ -88,6 +88,11 @@ describe('ReportUtils', () => {
         expect(ReportUtils.getIconsForGroupChat).toBeUndefined();
     });
 
+    it('does not export getIconsForUserCreatedPolicyRoom', () => {
+        // @ts-expect-error the test is asserting that it's undefined, so the TS error is normal
+        expect(ReportUtils.getIconsForUserCreatedPolicyRoom).toBeUndefined();
+    });
+
     it('does not export getAllReportActions', () => {
         // @ts-expect-error the test is asserting that it's undefined, so the TS error is normal
         expect(ReportUtils.getAllReportActions).toBeUndefined();
diff --git a/tests/unit/ReportUtilsGetIconsTest.ts b/tests/unit/ReportUtilsGetIconsTest.ts
index 2b30796a0384..7441f8d04f80 100644
--- a/tests/unit/ReportUtilsGetIconsTest.ts
+++ b/tests/unit/ReportUtilsGetIconsTest.ts
@@ -21,6 +21,7 @@ import {
     isSelfDM,
     isTaskReport,
     isThread,
+    isUserCreatedPolicyRoom,
     isWorkspaceTaskReport,
     isWorkspaceThread,
 } from '@libs/ReportUtils';
@@ -215,6 +216,25 @@ describe('getIcons', () => {
         expect(icons.at(0)?.name).toBe('Workspace-Test-001');
     });
 
+    it('should return the correct icons for a user created policy room', () => {
+        const report: Report = {
+            ...LHNTestUtils.getFakeReport([], 0, true),
+            chatType: CONST.REPORT.CHAT_TYPE.POLICY_ROOM,
+            policyID: '1',
+            avatarUrl: 'https://example.com/avatar.png',
+        };
+        const policy = LHNTestUtils.getFakePolicy('1');
+
+        // Verify report type conditions
+        expect(isUserCreatedPolicyRoom(report)).toBe(true);
+        expect(isChatReport(report)).toBe(true);
+
+        const icons = getIcons(report, FAKE_PERSONAL_DETAILS, null, '', -1, policy);
+        expect(icons).toHaveLength(1);
+        expect(icons.at(0)?.type).toBe(CONST.ICON_TYPE_WORKSPACE);
+        expect(icons.at(0)?.source).toBe('https://example.com/avatar.png');
+    });
+
     it('should return the correct icons for a policy expense chat', () => {
         const report: Report = {
             ...LHNTestUtils.getFakeReport([1], 0, true),
