diff --git a/locales/en-US.yml b/locales/en-US.yml
index 313514148f..527bee9af0 100644
--- a/locales/en-US.yml
+++ b/locales/en-US.yml
@@ -2839,3 +2839,4 @@ _selfXssPrevention:
 insertNewNotes: "Insert new notes at current position"
 insertNewNotesDescription: "Insert new notes at the current position while scrolling timeline."
 clickToShowInstanceTickerWindow: "Click InstanceTicker to show instance info"
+defaultLike: "Default like reaction"
diff --git a/packages/frontend/src/components/MkNote.vue b/packages/frontend/src/components/MkNote.vue
index a9f4ffba75..4eb3622515 100644
--- a/packages/frontend/src/components/MkNote.vue
+++ b/packages/frontend/src/components/MkNote.vue
@@ -320,6 +320,8 @@ const renoteCollapsed = ref(
 	),
 );
 
+const defaultLike = computed(() => defaultStore.state.like ? defaultStore.state.like : null);
+
 const inReplyToCollapsed = ref(defaultStore.state.collapseNotesRepliedTo);
 const disableReactionsViewer = ref(defaultStore.reactiveState.disableReactionsViewer);
 const collapsedUnexpectedLangs = ref(defaultStore.reactiveState.collapsedUnexpectedLangs);
@@ -500,15 +502,15 @@ function reply(): void {
 }
 
 function like(): void {
-	pleaseLogin(undefined, pleaseLoginContext.value);
+	pleaseLogin({ openOnRemote: pleaseLoginContext.value });
 	showMovedDialog();
 	sound.playMisskeySfx('reaction');
 	if (props.mock) {
 		return;
 	}
-	misskeyApi('notes/reactions/create', {
+	misskeyApi('notes/like', {
 		noteId: appearNote.value.id,
-		reaction: '❤️',
+		override: defaultLike.value,
 	});
 	const el = likeButton.value as HTMLElement | null | undefined;
 	if (el) {
@@ -531,9 +533,9 @@ function react(): void {
 			return;
 		}
 
-		misskeyApi('notes/reactions/create', {
+		misskeyApi('notes/like', {
 			noteId: appearNote.value.id,
-			reaction: '❤️',
+			override: defaultLike.value,
 		});
 		const el = reactButton.value;
 		if (el) {
diff --git a/packages/frontend/src/components/MkNoteDetailed.vue b/packages/frontend/src/components/MkNoteDetailed.vue
index 8ad128e54e..cfa0579bd2 100644
--- a/packages/frontend/src/components/MkNoteDetailed.vue
+++ b/packages/frontend/src/components/MkNoteDetailed.vue
@@ -348,6 +348,7 @@ const showTicker = (defaultStore.state.instanceTicker === 'always') || (defaultS
 const conversation = ref<Misskey.entities.Note[]>([]);
 const replies = ref<Misskey.entities.Note[]>([]);
 const canRenote = computed(() => ['public', 'home'].includes(appearNote.value.visibility) || appearNote.value.userId === $i?.id);
+const defaultLike = computed(() => defaultStore.state.like ? defaultStore.state.like : null);
 
 type ShowingNoteHistoryState = {
 	createdAt: string | null;
@@ -496,15 +497,12 @@ function reply(): void {
 }
 
 function like(): void {
-	pleaseLogin(undefined, pleaseLoginContext.value);
+	pleaseLogin({ openOnRemote: pleaseLoginContext.value });
 	showMovedDialog();
 	sound.playMisskeySfx('reaction');
-	if (props.mock) {
-		return;
-	}
-	misskeyApi('notes/reactions/create', {
+	misskeyApi('notes/like', {
 		noteId: appearNote.value.id,
-		reaction: '❤️',
+		override: defaultLike.value,
 	});
 	const el = likeButton.value as HTMLElement | null | undefined;
 	if (el) {
@@ -523,9 +521,9 @@ function react(): void {
 	if (appearNote.value.reactionAcceptance === 'likeOnly' || disableReactionsViewer.value) {
 		sound.playMisskeySfx('reaction');
 
-		misskeyApi('notes/reactions/create', {
+		misskeyApi('notes/like', {
 			noteId: appearNote.value.id,
-			reaction: '❤️',
+			override: defaultLike.value,
 		});
 		const el = reactButton.value;
 		if (el) {
diff --git a/packages/frontend/src/pages/settings/emoji-picker.vue b/packages/frontend/src/pages/settings/emoji-picker.vue
index fd3581d114..52331a8fa0 100644
--- a/packages/frontend/src/pages/settings/emoji-picker.vue
+++ b/packages/frontend/src/pages/settings/emoji-picker.vue
@@ -85,6 +85,17 @@ SPDX-License-Identifier: AGPL-3.0-only
 		</div>
 	</MkFolder>
 
+	<FromSlot>
+		<template #label>{{ i18n.ts.defaultLike }}</template>
+		<MkCustomEmoji v-if="like && like.startsWith(':')" style="max-height: 3em; font-size: 1.1em;" :useOriginalSize="false" :name="like" :normal="true" :noStyle="true"/>
+		<MkEmoji v-else-if="like && !like.startsWith(':')" :emoji="like" style="max-height: 3em; font-size: 1.1em;" :normal="true" :noStyle="true"/>
+		<span v-else-if="!like">{{ i18n.ts.notSet }}</span>
+		<div class="_buttons" style="padding-top: 8px;">
+			<MkButton rounded :small="true" inline @click="chooseNewLike"><i class="ti ti-plus"></i></MkButton>
+			<MkButton rounded :small="true" inline @click="resetLike"><i class="ti ti-refresh"></i></MkButton>
+		</div>
+	</FromSlot>
+
 	<FormSection>
 		<template #label>{{ i18n.ts.emojiPickerDisplay }}</template>
 
@@ -131,6 +142,7 @@ import Sortable from 'vuedraggable';
 import MkRadios from '@/components/MkRadios.vue';
 import MkButton from '@/components/MkButton.vue';
 import FormSection from '@/components/form/section.vue';
+import FromSlot from '@/components/form/slot.vue';
 import MkSelect from '@/components/MkSelect.vue';
 import * as os from '@/os.js';
 import { defaultStore } from '@/store.js';
@@ -155,6 +167,8 @@ const removeReaction = (reaction: string, ev: MouseEvent) => remove(pinnedEmojis
 const chooseReaction = (ev: MouseEvent) => pickEmoji(pinnedEmojisForReaction, ev);
 const setDefaultReaction = () => setDefault(pinnedEmojisForReaction);
 
+const like = computed(defaultStore.makeGetterSetter('like'));
+
 const removeEmoji = (reaction: string, ev: MouseEvent) => remove(pinnedEmojis, reaction, ev);
 const chooseEmoji = (ev: MouseEvent) => pickEmoji(pinnedEmojis, ev);
 const setDefaultEmoji = () => setDefault(pinnedEmojis);
@@ -223,6 +237,18 @@ async function pickEmoji(itemsRef: Ref<string[]>, ev: MouseEvent) {
 	});
 }
 
+function chooseNewLike(ev: MouseEvent) {
+	os.pickEmoji(getHTMLElement(ev), {
+		showPinned: false,
+	}).then(async emoji => {
+		defaultStore.set('like', emoji as string);
+	});
+}
+
+async function resetLike() {
+	defaultStore.set('like', null);
+}
+
 function getHTMLElement(ev: MouseEvent): HTMLElement {
 	const target = ev.currentTarget ?? ev.target;
 	return target as HTMLElement;
diff --git a/packages/frontend/src/store.ts b/packages/frontend/src/store.ts
index 57a0b63a7c..392de10117 100644
--- a/packages/frontend/src/store.ts
+++ b/packages/frontend/src/store.ts
@@ -136,6 +136,10 @@ export const defaultStore = markRaw(new Storage('base', {
 		where: 'account',
 		default: 'nonSensitiveOnly' as 'likeOnly' | 'likeOnlyForRemote' | 'nonSensitiveOnly' | 'nonSensitiveOnlyForLocalLikeOnlyForRemote' | null,
 	},
+	like: {
+		where: 'account',
+		default: null as string | null,
+	},
 	mutedAds: {
 		where: 'account',
 		default: [] as string[],