diff --git a/packages/backend/src/const.ts b/packages/backend/src/const.ts
index 6d3b9559e8d89e2dc99b8e98905f063f8f46510c..e2203b6b4589931b009c4ea3fb6ff32f51a13103 100644
--- a/packages/backend/src/const.ts
+++ b/packages/backend/src/const.ts
@@ -12,6 +12,7 @@ export const FILE_TYPE_BROWSERSAFE = [
 	'image/gif',
 	'image/jpeg',
 	'image/webp',
+	'image/avif',
 	'image/apng',
 	'image/bmp',
 	'image/tiff',
diff --git a/packages/backend/src/core/DriveService.ts b/packages/backend/src/core/DriveService.ts
index 895073c32c9cca379d972cd48e34bab152e73523..bbdb5fae8394a777546cc1ac043d011fc5b33876 100644
--- a/packages/backend/src/core/DriveService.ts
+++ b/packages/backend/src/core/DriveService.ts
@@ -138,6 +138,7 @@ export class DriveService {
 				if (type === 'image/jpeg') ext = '.jpg';
 				if (type === 'image/png') ext = '.png';
 				if (type === 'image/webp') ext = '.webp';
+				if (type === 'image/avif') ext = '.avif';
 				if (type === 'image/apng') ext = '.apng';
 				if (type === 'image/vnd.mozilla.apng') ext = '.apng';
 			}
@@ -262,7 +263,7 @@ export class DriveService {
 			}
 		}
 
-		if (!['image/jpeg', 'image/png', 'image/webp', 'image/svg+xml'].includes(type)) {
+		if (!['image/jpeg', 'image/png', 'image/webp', 'image/avif', 'image/svg+xml'].includes(type)) {
 			this.registerLogger.debug('web image and thumbnail not created (not an required file)');
 			return {
 				webpublic: null,
@@ -287,7 +288,7 @@ export class DriveService {
 			}
 
 			satisfyWebpublic = !!(
-				type !== 'image/svg+xml' && type !== 'image/webp' &&
+				type !== 'image/svg+xml' && type !== 'image/webp' && type !== 'image/avif' &&
 			!(metadata.exif ?? metadata.iptc ?? metadata.xmp ?? metadata.tifftagPhotoshop) &&
 			metadata.width && metadata.width <= 2048 &&
 			metadata.height && metadata.height <= 2048
@@ -307,7 +308,7 @@ export class DriveService {
 			this.registerLogger.info('creating web image');
 
 			try {
-				if (['image/jpeg', 'image/webp'].includes(type)) {
+				if (['image/jpeg', 'image/webp', 'image/avif'].includes(type)) {
 					webpublic = await this.imageProcessingService.convertSharpToJpeg(img, 2048, 2048);
 				} else if (['image/png'].includes(type)) {
 					webpublic = await this.imageProcessingService.convertSharpToPng(img, 2048, 2048);
@@ -329,7 +330,7 @@ export class DriveService {
 		let thumbnail: IImage | null = null;
 
 		try {
-			if (['image/jpeg', 'image/webp', 'image/png', 'image/svg+xml'].includes(type)) {
+			if (['image/jpeg', 'image/webp', 'image/avif', 'image/png', 'image/svg+xml'].includes(type)) {
 				thumbnail = await this.imageProcessingService.convertSharpToWebp(img, 498, 280);
 			} else {
 				this.registerLogger.debug('thumbnail not created (not an required file)');
diff --git a/packages/backend/src/core/FileInfoService.ts b/packages/backend/src/core/FileInfoService.ts
index bea1b3402e2d1a164abab15cd45c61bdbfbd0abb..804399304768b4d8259de43df7c4744786e34d97 100644
--- a/packages/backend/src/core/FileInfoService.ts
+++ b/packages/backend/src/core/FileInfoService.ts
@@ -73,7 +73,18 @@ export class FileInfoService {
 		let height: number | undefined;
 		let orientation: number | undefined;
 
-		if (['image/jpeg', 'image/gif', 'image/png', 'image/apng', 'image/webp', 'image/bmp', 'image/tiff', 'image/svg+xml', 'image/vnd.adobe.photoshop'].includes(type.mime)) {
+		if ([
+			'image/png',
+			'image/gif',
+			'image/jpeg',
+			'image/webp',
+			'image/avif',
+			'image/apng',
+			'image/bmp',
+			'image/tiff',
+			'image/svg+xml',
+			'image/vnd.adobe.photoshop',
+		].includes(type.mime)) {
 			const imageSize = await this.detectImageSize(path).catch(e => {
 				warnings.push(`detectImageSize failed: ${e}`);
 				return undefined;
@@ -100,7 +111,15 @@ export class FileInfoService {
 
 		let blurhash: string | undefined;
 
-		if (['image/jpeg', 'image/gif', 'image/png', 'image/apng', 'image/webp', 'image/svg+xml'].includes(type.mime)) {
+		if ([
+			'image/jpeg',
+			'image/gif',
+			'image/png',
+			'image/apng',
+			'image/webp',
+			'image/avif',
+			'image/svg+xml',
+		].includes(type.mime)) {
 			blurhash = await this.getBlurhash(path).catch(e => {
 				warnings.push(`getBlurhash failed: ${e}`);
 				return undefined;
@@ -156,7 +175,11 @@ export class FileInfoService {
 			return [sensitive, porn];
 		}
 	
-		if (['image/jpeg', 'image/png', 'image/webp'].includes(mime)) {
+		if ([
+			'image/jpeg',
+			'image/png',
+			'image/webp',
+		].includes(mime)) {
 			const result = await this.aiService.detectSensitive(source);
 			if (result) {
 				[sensitive, porn] = judgePrediction(result);
diff --git a/packages/backend/src/core/entities/DriveFileEntityService.ts b/packages/backend/src/core/entities/DriveFileEntityService.ts
index 706c8c118616c16d7dc7944ae4bcd2390847aba9..7f54cfdeaca0462b5bb187f97bad708637300e9f 100644
--- a/packages/backend/src/core/entities/DriveFileEntityService.ts
+++ b/packages/backend/src/core/entities/DriveFileEntityService.ts
@@ -89,7 +89,7 @@ export class DriveFileEntityService {
 			}
 		}
 
-		const isImage = file.type && ['image/png', 'image/apng', 'image/gif', 'image/jpeg', 'image/webp', 'image/svg+xml'].includes(file.type);
+		const isImage = file.type && ['image/png', 'image/apng', 'image/gif', 'image/jpeg', 'image/webp', 'image/avif', 'image/svg+xml'].includes(file.type);
 
 		return thumbnail ? (file.thumbnailUrl ?? (isImage ? (file.webpublicUrl ?? file.url) : null)) : (file.webpublicUrl ?? file.url);
 	}
diff --git a/packages/backend/src/misc/is-mime-image.ts b/packages/backend/src/misc/is-mime-image.ts
index 8993ede33a4700c30ecdeae3bd73ddcaade28677..168a9a7af6375326465f21d4c3517aa13f2f1eb7 100644
--- a/packages/backend/src/misc/is-mime-image.ts
+++ b/packages/backend/src/misc/is-mime-image.ts
@@ -2,7 +2,7 @@ import { FILE_TYPE_BROWSERSAFE } from '@/const.js';
 
 const dictionary = {
 	'safe-file': FILE_TYPE_BROWSERSAFE,
-	'sharp-convertible-image': ['image/jpeg', 'image/png', 'image/gif', 'image/apng', 'image/vnd.mozilla.apng', 'image/webp', 'image/svg+xml'],
+	'sharp-convertible-image': ['image/jpeg', 'image/png', 'image/gif', 'image/apng', 'image/vnd.mozilla.apng', 'image/webp', 'image/avif', 'image/svg+xml'],
 };
 
 export const isMimeImage = (mime: string, type: keyof typeof dictionary): boolean => dictionary[type].includes(mime);
diff --git a/packages/backend/src/server/FileServerService.ts b/packages/backend/src/server/FileServerService.ts
index b7ab5496116f4a4471be98edf95da3282b0c7add..8b1a1306576922419fac14c52a9376f820ec87b3 100644
--- a/packages/backend/src/server/FileServerService.ts
+++ b/packages/backend/src/server/FileServerService.ts
@@ -114,7 +114,7 @@ export class FileServerService {
 
 					const convertFile = async () => {
 						if (isThumbnail) {
-							if (['image/jpeg', 'image/webp', 'image/png', 'image/svg+xml'].includes(mime)) {
+							if (['image/jpeg', 'image/webp', 'image/avif', 'image/png', 'image/svg+xml'].includes(mime)) {
 								return await this.imageProcessingService.convertToWebp(path, 498, 280);
 							} else if (mime.startsWith('video/')) {
 								return await this.videoProcessingService.generateVideoThumbnail(path);
diff --git a/packages/client/src/const.ts b/packages/client/src/const.ts
index 505cf2748e6bffb9bcb39cc7937481d61587b16d..77366cf07b96d378b691d30c512807724e465aef 100644
--- a/packages/client/src/const.ts
+++ b/packages/client/src/const.ts
@@ -7,6 +7,7 @@ export const FILE_TYPE_BROWSERSAFE = [
 	'image/gif',
 	'image/jpeg',
 	'image/webp',
+	'image/avif',
 	'image/apng',
 	'image/bmp',
 	'image/tiff',
diff --git a/packages/client/src/pages/user/index.photos.vue b/packages/client/src/pages/user/index.photos.vue
index 5c9a73dcb712d3de3895c7e64feafae49f1009f0..fae2c005d83bca867f8df5cea78af7888cf58254 100644
--- a/packages/client/src/pages/user/index.photos.vue
+++ b/packages/client/src/pages/user/index.photos.vue
@@ -47,6 +47,8 @@ function thumbnail(image: misskey.entities.DriveFile): string {
 onMounted(() => {
 	const image = [
 		'image/jpeg',
+		'image/webp',
+		'image/avif',
 		'image/png',
 		'image/gif',
 		'image/apng',