diff --git a/locales/ja-JP.yml b/locales/ja-JP.yml
index f4c22d1fffdb9882a054c73c57e8d0a04703add3..58e9132cf33baaab263aaf6a5062d717e044a38f 100644
--- a/locales/ja-JP.yml
+++ b/locales/ja-JP.yml
@@ -597,6 +597,12 @@ openInNewTab: "新しいタブで開く"
 openInSideView: "サイドビューで開く"
 defaultNavigationBehaviour: "デフォルトのナビゲーション"
 editTheseSettingsMayBreakAccount: "これらの設定を編集するとアカウントが破損する可能性があります。"
+instanceTicker: "ノートのインスタンス情報"
+
+_instanceTicker:
+  none: "表示しない"
+  remote: "リモートユーザーに表示"
+  always: "常に表示"
 
 _serverDisconnectedBehavior:
   reload: "自動でリロード"
diff --git a/migration/1603776877564-instance-theme-color.ts b/migration/1603776877564-instance-theme-color.ts
new file mode 100644
index 0000000000000000000000000000000000000000..80c9d516fc2d0229381f5b5eaf3c88286245defe
--- /dev/null
+++ b/migration/1603776877564-instance-theme-color.ts
@@ -0,0 +1,14 @@
+import {MigrationInterface, QueryRunner} from "typeorm";
+
+export class instanceThemeColor1603776877564 implements MigrationInterface {
+    name = 'instanceThemeColor1603776877564'
+
+    public async up(queryRunner: QueryRunner): Promise<void> {
+        await queryRunner.query(`ALTER TABLE "instance" ADD "themeColor" character varying(64) DEFAULT null`);
+    }
+
+    public async down(queryRunner: QueryRunner): Promise<void> {
+        await queryRunner.query(`ALTER TABLE "instance" DROP COLUMN "themeColor"`);
+    }
+
+}
diff --git a/migration/1603781553011-instance-favicon.ts b/migration/1603781553011-instance-favicon.ts
new file mode 100644
index 0000000000000000000000000000000000000000..d748c43f5edd02a6f73888dd7edf143933ff988e
--- /dev/null
+++ b/migration/1603781553011-instance-favicon.ts
@@ -0,0 +1,14 @@
+import {MigrationInterface, QueryRunner} from "typeorm";
+
+export class instanceFavicon1603781553011 implements MigrationInterface {
+    name = 'instanceFavicon1603781553011'
+
+    public async up(queryRunner: QueryRunner): Promise<void> {
+        await queryRunner.query(`ALTER TABLE "instance" ADD "faviconUrl" character varying(256) DEFAULT null`);
+    }
+
+    public async down(queryRunner: QueryRunner): Promise<void> {
+        await queryRunner.query(`ALTER TABLE "instance" DROP COLUMN "faviconUrl"`);
+    }
+
+}
diff --git a/src/client/components/instance-ticker.vue b/src/client/components/instance-ticker.vue
new file mode 100644
index 0000000000000000000000000000000000000000..9447e6d4c3258d02679f6bc31e2df574a9c91704
--- /dev/null
+++ b/src/client/components/instance-ticker.vue
@@ -0,0 +1,61 @@
+<template>
+<div class="hpaizdrt" :style="bg">
+	<img v-if="info.faviconUrl" class="icon" :src="info.faviconUrl"/>
+	<span class="name">{{ info.name }}</span>
+</div>
+</template>
+
+<script lang="ts">
+import { defineComponent } from 'vue';
+import { instanceName } from '@/config';
+
+export default defineComponent({
+	props: {
+		instance: {
+			type: Object,
+			required: false
+		},
+	},
+
+	data() {
+		return {
+			info: this.instance || {
+				faviconUrl: '/favicon.ico',
+				name: instanceName,
+				themeColor: (document.querySelector('meta[name="theme-color-orig"]') as HTMLMetaElement)?.content
+			}
+		}
+	},
+
+	computed: {
+		bg(): any {
+			return this.info.themeColor ? {
+				background: `linear-gradient(90deg, ${this.info.themeColor}, ${this.info.themeColor + '00'})`
+			} : null;
+		}
+	}
+});
+</script>
+
+<style lang="scss" scoped>
+.hpaizdrt {
+	$height: 1.1rem;
+
+	height: $height;
+	border-radius: 4px 0 0 4px;
+	overflow: hidden;
+	color: #fff;
+
+	> .icon {
+		height: 100%;
+	}
+
+	> .name {
+		margin-left: 4px;
+		line-height: $height;
+		font-size: 0.9em;
+		vertical-align: top;
+		font-weight: bold;
+	}
+}
+</style>
diff --git a/src/client/components/note.vue b/src/client/components/note.vue
index 8ddb01f733db0378f985f94d55cd04868f677191..4e31aec12e67907622e20cf09af7da27009ee210 100644
--- a/src/client/components/note.vue
+++ b/src/client/components/note.vue
@@ -40,6 +40,7 @@
 		<MkAvatar class="avatar" :user="appearNote.user"/>
 		<div class="main">
 			<XNoteHeader class="header" :note="appearNote" :mini="true"/>
+			<MkInstanceTicker v-if="showTicker" class="ticker" :instance="appearNote.user.instance"/>
 			<div class="body" ref="noteBody">
 				<p v-if="appearNote.cw != null" class="cw">
 					<Mfm v-if="appearNote.cw != ''" class="text" :text="appearNote.cw" :author="appearNote.user" :i="$store.state.i" :custom-emojis="appearNote.emojis"/>
@@ -139,6 +140,7 @@ export default defineComponent({
 		XCwButton,
 		XPoll,
 		MkUrlPreview: defineAsyncComponent(() => import('@/components/url-preview.vue')),
+		MkInstanceTicker: defineAsyncComponent(() => import('@/components/instance-ticker.vue')),
 	},
 
 	inject: {
@@ -258,6 +260,12 @@ export default defineComponent({
 			} else {
 				return null;
 			}
+		},
+
+		showTicker() {
+			if (this.$store.state.device.instanceTicker === 'always') return true;
+			if (this.$store.state.device.instanceTicker === 'remote' && this.appearNote.user.instance) return true;
+			return false;
 		}
 	},
 
diff --git a/src/client/components/sidebar.vue b/src/client/components/sidebar.vue
index 3ceb1f9b8d951607b6450318e1be5a694de5a848..bd19cf1a74ab981ad989ed85d82f001660bc8c81 100644
--- a/src/client/components/sidebar.vue
+++ b/src/client/components/sidebar.vue
@@ -246,7 +246,7 @@ export default defineComponent({
 				icon: faQuestionCircle,
 			}, {
 				type: 'link',
-				text: this.$t('aboutX', { x: instanceName || host }),
+				text: this.$t('aboutX', { x: instanceName }),
 				to: '/about',
 				icon: faInfoCircle,
 			}, {
diff --git a/src/client/config.ts b/src/client/config.ts
index ac8d7d95287d8b3673e4814c2a481c0caa9fee0c..e0d2fd1deb287ed4c12b1a8ec41f5e905bd45537 100644
--- a/src/client/config.ts
+++ b/src/client/config.ts
@@ -12,5 +12,5 @@ export const lang = localStorage.getItem('lang');
 export const langs = _LANGS_;
 export const getLocale = async () => Object.fromEntries((await entries(clientDb.i18n)) as [string, string][]);
 export const version = _VERSION_;
-export const instanceName = siteName === 'Misskey' ? null : siteName;
+export const instanceName = siteName === 'Misskey' ? host : siteName;
 export const deckmode = localStorage.getItem('deckmode') === 'true';
diff --git a/src/client/pages/settings/general.vue b/src/client/pages/settings/general.vue
index d61d8620e775d49f5cd8e84b98b454bead9c360d..0db571ff147658442a883765410fe4b1bcf353a3 100644
--- a/src/client/pages/settings/general.vue
+++ b/src/client/pages/settings/general.vue
@@ -51,6 +51,12 @@
 			<MkRadio v-model="fontSize" value="large"><span style="font-size: 18px;">Aa</span></MkRadio>
 			<MkRadio v-model="fontSize" value="veryLarge"><span style="font-size: 20px;">Aa</span></MkRadio>
 		</div>
+		<div class="_content">
+			<div>{{ $t('instanceTicker') }}</div>
+			<MkRadio v-model="instanceTicker" value="none">{{ $t('_instanceTicker.none') }}</MkRadio>
+			<MkRadio v-model="instanceTicker" value="remote">{{ $t('_instanceTicker.remote') }}</MkRadio>
+			<MkRadio v-model="instanceTicker" value="always">{{ $t('_instanceTicker.always') }}</MkRadio>
+		</div>
 	</section>
 
 	<section class="_card _vMargin">
@@ -169,6 +175,11 @@ export default defineComponent({
 			set(value) { this.$store.commit('device/set', { key: 'chatOpenBehavior', value }); }
 		},
 
+		instanceTicker: {
+			get() { return this.$store.state.device.instanceTicker; },
+			set(value) { this.$store.commit('device/set', { key: 'instanceTicker', value }); }
+		},
+
 		enableInfiniteScroll: {
 			get() { return this.$store.state.device.enableInfiniteScroll; },
 			set(value) { this.$store.commit('device/set', { key: 'enableInfiniteScroll', value }); }
diff --git a/src/client/store.ts b/src/client/store.ts
index 5dc35bb42ec60a0f83e70c7d92b96357b72dd347..5c6c71d4f217ecc9d57c446d45cadb2263806238 100644
--- a/src/client/store.ts
+++ b/src/client/store.ts
@@ -77,6 +77,7 @@ export const defaultDeviceSettings = {
 	enableInfiniteScroll: true,
 	useBlurEffectForModal: true,
 	sidebarDisplay: 'full', // full, icon, hide
+	instanceTicker: 'remote', // none, remote, always
 	roomGraphicsQuality: 'medium',
 	roomUseOrthographicCamera: true,
 	deckColumnAlign: 'left',
diff --git a/src/client/ui/visitor.vue b/src/client/ui/visitor.vue
index 8b7dfd791183b4177a4779b0cc6909a46ed185c5..8a3c19b6319a0b80bba424907ba69b48d6c15888 100644
--- a/src/client/ui/visitor.vue
+++ b/src/client/ui/visitor.vue
@@ -4,11 +4,11 @@
 		<MkA class="link" to="/">{{ $t('home') }}</MkA>
 		<MkA class="link" to="/announcements">{{ $t('announcements') }}</MkA>
 		<MkA class="link" to="/channels">{{ $t('channel') }}</MkA>
-		<MkA class="link" to="/about">{{ $t('aboutX', { x: instanceName || host }) }}</MkA>
+		<MkA class="link" to="/about">{{ $t('aboutX', { x: instanceName }) }}</MkA>
 	</header>
 
 	<div class="banner" :style="{ backgroundImage: `url(${ $store.state.instance.meta.bannerUrl })` }">
-		<h1>{{ instanceName || host }}</h1>
+		<h1>{{ instanceName }}</h1>
 	</div>
 
 	<div class="contents" ref="contents" :class="{ wallpaper }">
diff --git a/src/models/entities/instance.ts b/src/models/entities/instance.ts
index 5fedfc0956c7c7ac39b4b08b5005d4f4745c8bbe..7c8719e06ae7bff2a6de5bbc4930d3cdc63c082f 100644
--- a/src/models/entities/instance.ts
+++ b/src/models/entities/instance.ts
@@ -163,6 +163,16 @@ export class Instance {
 	})
 	public iconUrl: string | null;
 
+	@Column('varchar', {
+		length: 256, nullable: true, default: null,
+	})
+	public faviconUrl: string | null;
+
+	@Column('varchar', {
+		length: 64, nullable: true, default: null,
+	})
+	public themeColor: string | null;
+
 	@Column('timestamp with time zone', {
 		nullable: true,
 	})
diff --git a/src/models/repositories/user.ts b/src/models/repositories/user.ts
index 7ea4d42bcb5d548cb073cc8df9cfc0b87644c0c2..4ac7c6d85d02ed5f8013d8adb90eacb113a1864a 100644
--- a/src/models/repositories/user.ts
+++ b/src/models/repositories/user.ts
@@ -1,7 +1,7 @@
 import $ from 'cafy';
 import { EntityRepository, Repository, In, Not } from 'typeorm';
 import { User, ILocalUser, IRemoteUser } from '../entities/user';
-import { Emojis, Notes, NoteUnreads, FollowRequests, Notifications, MessagingMessages, UserNotePinings, Followings, Blockings, Mutings, UserProfiles, UserSecurityKeys, UserGroupJoinings, Pages, Announcements, AnnouncementReads, Antennas, AntennaNotes, ChannelFollowings } from '..';
+import { Emojis, Notes, NoteUnreads, FollowRequests, Notifications, MessagingMessages, UserNotePinings, Followings, Blockings, Mutings, UserProfiles, UserSecurityKeys, UserGroupJoinings, Pages, Announcements, AnnouncementReads, Antennas, AntennaNotes, ChannelFollowings, Instances } from '..';
 import { ensure } from '../../prelude/ensure';
 import config from '../../config';
 import { SchemaType } from '../../misc/schema';
@@ -181,6 +181,14 @@ export class UserRepository extends Repository<User> {
 			isModerator: user.isModerator || falsy,
 			isBot: user.isBot || falsy,
 			isCat: user.isCat || falsy,
+			instance: user.host ? Instances.findOne({ host: user.host }).then(instance => instance ? {
+				name: instance.name,
+				softwareName: instance.softwareName,
+				softwareVersion: instance.softwareVersion,
+				iconUrl: instance.iconUrl,
+				faviconUrl: instance.faviconUrl,
+				themeColor: instance.themeColor,
+			} : undefined) : undefined,
 
 			// カスタム絵文字添付
 			emojis: user.emojis.length > 0 ? Emojis.find({
diff --git a/src/server/web/views/base.pug b/src/server/web/views/base.pug
index d3f0106ac1215c179a0a38c98e6e344bea2eee57..9652d29dbb2c3f3bc476f535201cadfbaa0a5bd5 100644
--- a/src/server/web/views/base.pug
+++ b/src/server/web/views/base.pug
@@ -11,6 +11,7 @@ html
 		meta(name='application-name' content='Misskey')
 		meta(name='referrer' content='origin')
 		meta(name='theme-color' content='#86b300')
+		meta(name='theme-color-orig' content='#86b300')
 		meta(property='og:site_name' content= instanceName || 'Misskey')
 		meta(name='viewport' content='width=device-width, initial-scale=1')
 		link(rel='icon' href= icon || '/favicon.ico')
diff --git a/src/services/fetch-instance-metadata.ts b/src/services/fetch-instance-metadata.ts
index 41fef859c90fec350e0b83ee9e4b7284fe70c852..487421816a4fa4ea354eef4c228cf2d90e8ce6d6 100644
--- a/src/services/fetch-instance-metadata.ts
+++ b/src/services/fetch-instance-metadata.ts
@@ -1,4 +1,4 @@
-import { JSDOM } from 'jsdom';
+import { DOMWindow, JSDOM } from 'jsdom';
 import fetch from 'node-fetch';
 import { getJson, getHtml, getAgentByUrl } from '../misc/fetch';
 import { Instance } from '../models/entities/instance';
@@ -22,9 +22,18 @@ export async function fetchInstanceMetadata(instance: Instance): Promise<void> {
 	logger.info(`Fetching metadata of ${instance.host} ...`);
 
 	try {
-		const [info, icon] = await Promise.all([
+		const [info, dom, manifest] = await Promise.all([
 			fetchNodeinfo(instance).catch(() => null),
-			fetchIconUrl(instance).catch(() => null),
+			fetchDom(instance).catch(() => null),
+			fetchManifest(instance).catch(() => null),
+		]);
+
+		const [favicon, icon, themeColor, name, description] = await Promise.all([
+			fetchFaviconUrl(instance).catch(() => null),
+			fetchIconUrl(instance, dom, manifest).catch(() => null),
+			getThemeColor(dom, manifest).catch(() => null),
+			getSiteName(info, dom, manifest).catch(() => null),
+			getDescription(info, dom, manifest).catch(() => null),
 		]);
 
 		logger.succ(`Successfuly fetched metadata of ${instance.host}`);
@@ -34,18 +43,18 @@ export async function fetchInstanceMetadata(instance: Instance): Promise<void> {
 		} as Record<string, any>;
 
 		if (info) {
-			updates.softwareName = info.software.name.toLowerCase();
-			updates.softwareVersion = info.software.version;
+			updates.softwareName = info.software?.name.toLowerCase();
+			updates.softwareVersion = info.software?.version;
 			updates.openRegistrations = info.openRegistrations;
-			updates.name = info.metadata ? (info.metadata.nodeName || info.metadata.name || null) : null;
-			updates.description = info.metadata ? (info.metadata.nodeDescription || info.metadata.description || null) : null;
 			updates.maintainerName = info.metadata ? info.metadata.maintainer ? (info.metadata.maintainer.name || null) : null : null;
 			updates.maintainerEmail = info.metadata ? info.metadata.maintainer ? (info.metadata.maintainer.email || null) : null : null;
 		}
 
-		if (icon) {
-			updates.iconUrl = icon;
-		}
+		if (name) updates.name = name;
+		if (description) updates.description = description;
+		if (icon || favicon) updates.iconUrl = icon || favicon;
+		if (favicon) updates.faviconUrl = favicon;
+		if (themeColor) updates.themeColor = themeColor;
 
 		await Instances.update(instance.id, updates);
 
@@ -57,7 +66,25 @@ export async function fetchInstanceMetadata(instance: Instance): Promise<void> {
 	}
 }
 
-async function fetchNodeinfo(instance: Instance): Promise<Record<string, any>> {
+type NodeInfo = {
+	openRegistrations?: any;
+	software?: {
+		name?: any;
+		version?: any;
+	};
+	metadata?: {
+		name?: any;
+		nodeName?: any;
+		nodeDescription?: any;
+		description?: any;
+		maintainer?: {
+			name?: any;
+			email?: any;
+		};
+	};
+};
+
+async function fetchNodeinfo(instance: Instance): Promise<NodeInfo> {
 	logger.info(`Fetching nodeinfo of ${instance.host} ...`);
 
 	try {
@@ -100,8 +127,8 @@ async function fetchNodeinfo(instance: Instance): Promise<Record<string, any>> {
 	}
 }
 
-async function fetchIconUrl(instance: Instance): Promise<string | null> {
-	logger.info(`Fetching icon URL of ${instance.host} ...`);
+async function fetchDom(instance: Instance): Promise<DOMWindow['document']> {
+	logger.info(`Fetching HTML of ${instance.host} ...`);
 
 	const url = 'https://' + instance.host;
 
@@ -110,16 +137,23 @@ async function fetchIconUrl(instance: Instance): Promise<string | null> {
 	const { window } = new JSDOM(html);
 	const doc = window.document;
 
-	const hrefAppleTouchIconPrecomposed = doc.querySelector('link[rel="apple-touch-icon-precomposed"]')?.getAttribute('href');
-	const hrefAppleTouchIcon = doc.querySelector('link[rel="apple-touch-icon"]')?.getAttribute('href');
-	const hrefIcon = doc.querySelector('link[rel="icon"]')?.getAttribute('href');
+	return doc;
+}
 
-	const href = hrefAppleTouchIconPrecomposed || hrefAppleTouchIcon || hrefIcon;
+async function fetchManifest(instance: Instance): Promise<Record<string, any> | null> {
+	const url = 'https://' + instance.host;
 
-	if (href) {
-		return (new URL(href, url)).href;
-	}
+	const manifestUrl = url + '/manifest.json';
+
+	const manifest = await getJson(manifestUrl);
 
+	return manifest;
+}
+
+async function fetchFaviconUrl(instance: Instance): Promise<string | null> {
+	logger.info(`Fetching favicon URL of ${instance.host} ...`);
+
+	const url = 'https://' + instance.host;
 	const faviconUrl = url + '/favicon.ico';
 
 	const favicon = await fetch(faviconUrl, {
@@ -133,3 +167,90 @@ async function fetchIconUrl(instance: Instance): Promise<string | null> {
 
 	return null;
 }
+
+async function fetchIconUrl(instance: Instance, doc: DOMWindow['document'] | null, manifest: Record<string, any> | null): Promise<string | null> {
+	if (doc) {
+		const url = 'https://' + instance.host;
+
+		const hrefAppleTouchIconPrecomposed = doc.querySelector('link[rel="apple-touch-icon-precomposed"]')?.getAttribute('href');
+		const hrefAppleTouchIcon = doc.querySelector('link[rel="apple-touch-icon"]')?.getAttribute('href');
+		const hrefIcon = doc.querySelector('link[rel="icon"]')?.getAttribute('href');
+
+		const href = hrefAppleTouchIconPrecomposed || hrefAppleTouchIcon || hrefIcon;
+
+		if (href) {
+			return (new URL(href, url)).href;
+		}
+	}
+
+	if (manifest && manifest.icons && manifest.icons.length > 0 && manifest.icons[0].src) {
+		const url = 'https://' + instance.host;
+		return (new URL(manifest.icons[0].src, url)).href;
+	}
+
+	return null;
+}
+
+async function getThemeColor(doc: DOMWindow['document'] | null, manifest: Record<string, any> | null): Promise<string | null> {
+	if (doc) {
+		const themeColor = doc.querySelector('meta[name="theme-color"]')?.getAttribute('content');
+
+		if (themeColor) {
+			return themeColor;
+		}
+	}
+
+	if (manifest) {
+		return manifest.theme_color;
+	}
+
+	return null;
+}
+
+async function getSiteName(info: NodeInfo | null, doc: DOMWindow['document'] | null, manifest: Record<string, any> | null): Promise<string | null> {
+	if (info && info.metadata) {
+		if (info.metadata.nodeName || info.metadata.name) {
+			return info.metadata.nodeName || info.metadata.name;
+		}
+	}
+
+	if (doc) {
+		const og = doc.querySelector('meta[property="og:title"]')?.getAttribute('content');
+
+		if (og) {
+			return og;
+		}
+	}
+
+	if (manifest) {
+		return manifest?.name || manifest?.short_name;
+	}
+
+	return null;
+}
+
+async function getDescription(info: NodeInfo | null, doc: DOMWindow['document'] | null, manifest: Record<string, any> | null): Promise<string | null> {
+	if (info && info.metadata) {
+		if (info.metadata.nodeDescription || info.metadata.description) {
+			return info.metadata.nodeDescription || info.metadata.description;
+		}
+	}
+
+	if (doc) {
+		const meta = doc.querySelector('meta[name="description"]')?.getAttribute('content');
+		if (meta) {
+			return meta;
+		}
+
+		const og = doc.querySelector('meta[property="og:description"]')?.getAttribute('content');
+		if (og) {
+			return og;
+		}
+	}
+
+	if (manifest) {
+		return manifest?.name || manifest?.short_name;
+	}
+
+	return null;
+}