diff --git a/packages/client/assets/dummy.png b/packages/client/assets/dummy.png
new file mode 100644
index 000000000..1703badd7
--- /dev/null
+++ b/packages/client/assets/dummy.png
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:fe0f4c44a5e63ac228fafc6fa3aba1fbe88188dea73ca39d2f8c950f17f74d47
+size 6285
diff --git a/packages/client/src/ui/_common_/statusbar-federation.vue b/packages/client/src/ui/_common_/statusbar-federation.vue
index f29c6a9ff..2896cc09c 100644
--- a/packages/client/src/ui/_common_/statusbar-federation.vue
+++ b/packages/client/src/ui/_common_/statusbar-federation.vue
@@ -4,7 +4,7 @@
 		<transition name="change" mode="default">
 			<MarqueeText :key="key" :duration="marqueeDuration" :reverse="marqueeReverse">
 				<span v-for="instance in instances" :key="instance.id" class="item" :class="{ colored }" :style="{ background: colored ? instance.themeColor : null }">
-					<img v-if="instance.iconUrl" class="icon" :src="instance.iconUrl" alt=""/>
+					<img class="icon" :src="getInstanceIcon(instance)" alt=""/>
 					<MkA :to="`/instance-info/${instance.host}`" class="host _monospace">
 						{{ instance.host }}
 					</MkA>
@@ -27,6 +27,7 @@ import * as os from '@/os';
 import { useInterval } from '@/scripts/use-interval';
 import { getNoteSummary } from '@/scripts/get-note-summary';
 import { notePage } from '@/filters/note';
+import { getProxiedImageUrlNullable } from '@/scripts/media-proxy';
 
 const props = defineProps<{
 	display?: 'marquee' | 'oneByOne';
@@ -56,6 +57,10 @@ useInterval(tick, Math.max(5000, props.refreshIntervalSec * 1000), {
 	immediate: true,
 	afterMounted: true,
 });
+
+function getInstanceIcon(instance): string {
+	return getProxiedImageUrlNullable(instance.iconUrl, 'preview') ?? getProxiedImageUrlNullable(instance.faviconUrl, 'preview') ?? '/client-assets/dummy.png';
+}
 </script>
 
 <style lang="scss" scoped>
diff --git a/packages/client/src/widgets/federation.vue b/packages/client/src/widgets/federation.vue
index cbbd3eb94..706712668 100644
--- a/packages/client/src/widgets/federation.vue
+++ b/packages/client/src/widgets/federation.vue
@@ -6,7 +6,7 @@
 		<MkLoading v-if="fetching"/>
 		<transition-group v-else tag="div" :name="$store.state.animation ? 'chart' : ''" class="instances">
 			<div v-for="(instance, i) in instances" :key="instance.id" class="instance">
-				<img v-if="instance.iconUrl" :src="instance.iconUrl" alt=""/>
+				<img :src="getInstanceIcon(instance)" alt=""/>
 				<div class="body">
 					<a class="a" :href="'https://' + instance.host" target="_blank" :title="instance.host">{{ instance.host }}</a>
 					<p>{{ instance.softwareName || '?' }} {{ instance.softwareVersion }}</p>
@@ -27,6 +27,7 @@ import MkMiniChart from '@/components/MkMiniChart.vue';
 import * as os from '@/os';
 import { useInterval } from '@/scripts/use-interval';
 import { i18n } from '@/i18n';
+import { getProxiedImageUrlNullable } from '@/scripts/media-proxy';
 
 const name = 'federation';
 
@@ -71,6 +72,10 @@ useInterval(fetch, 1000 * 60, {
 	afterMounted: true,
 });
 
+function getInstanceIcon(instance): string {
+	return getProxiedImageUrlNullable(instance.iconUrl, 'preview') ?? getProxiedImageUrlNullable(instance.faviconUrl, 'preview') ?? '/client-assets/dummy.png';
+}
+
 defineExpose<WidgetComponentExpose>({
 	name,
 	configure,
diff --git a/packages/client/src/widgets/instance-cloud.vue b/packages/client/src/widgets/instance-cloud.vue
index 1358a63b6..3cb579c28 100644
--- a/packages/client/src/widgets/instance-cloud.vue
+++ b/packages/client/src/widgets/instance-cloud.vue
@@ -4,7 +4,7 @@
 		<MkTagCloud v-if="activeInstances">
 			<li v-for="instance in activeInstances" :key="instance.id">
 				<a @click.prevent="onInstanceClick(instance)">
-					<img style="width: 32px;" :src="instance.iconUrl">
+					<img style="width: 32px;" :src="getInstanceIcon(instance)">
 				</a>
 			</li>
 		</MkTagCloud>
@@ -21,6 +21,7 @@ import MkContainer from '@/components/MkContainer.vue';
 import MkTagCloud from '@/components/MkTagCloud.vue';
 import * as os from '@/os';
 import { useInterval } from '@/scripts/use-interval';
+import { getProxiedImageUrlNullable } from '@/scripts/media-proxy';
 
 const name = 'instanceCloud';
 
@@ -65,6 +66,10 @@ useInterval(() => {
 	afterMounted: true,
 });
 
+function getInstanceIcon(instance): string {
+	return getProxiedImageUrlNullable(instance.iconUrl, 'preview') ?? getProxiedImageUrlNullable(instance.faviconUrl, 'preview') ?? '/client-assets/dummy.png';
+}
+
 defineExpose<WidgetComponentExpose>({
 	name,
 	configure,