diff --git a/Cargo.lock b/Cargo.lock
index 7838334..7c38c3c 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -1160,9 +1160,9 @@ checksum = "cd179ae861f0c2e53da70d892f5f3029f9594be0c41dc5269cd371691b1dc2f9"
 
 [[package]]
 name = "id3"
-version = "0.6.3"
+version = "0.6.4"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f23fa956cb2f3e3e547993eb62b6f76b5babd86c3e7bb4fe1149ef192d90df51"
+checksum = "bbe9b826aaa15b25bfb73c18ca9507a0ced87578a62376a7751dc6a510e3d244"
 dependencies = [
  "bitflags",
  "byteorder",
diff --git a/Cargo.toml b/Cargo.toml
index 20caa2b..689e18a 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -24,7 +24,7 @@ diesel_migrations = { version = "1.4", features = ["sqlite"] }
 futures-util = { version = "0.3" }
 getopts = "0.2.15"
 http = "0.2.2"
-id3 = "0.6.3"
+id3 = "0.6.4"
 libsqlite3-sys = { version = "0.18", features = ["bundled", "bundled-windows"], optional = true }
 lewton = "0.10.1"
 log = "0.4.5"
diff --git a/src/app/index/metadata.rs b/src/app/index/metadata.rs
index 9751548..34fb98a 100644
--- a/src/app/index/metadata.rs
+++ b/src/app/index/metadata.rs
@@ -59,6 +59,7 @@ impl From<id3::Tag> for SongTags {
 
 pub fn read(path: &Path) -> Option<SongTags> {
 	let data = match utils::get_audio_format(path) {
+		Some(AudioFormat::AIFF) => Some(read_aiff(path)),
 		Some(AudioFormat::APE) => Some(read_ape(path)),
 		Some(AudioFormat::FLAC) => Some(read_flac(path)),
 		Some(AudioFormat::MP3) => Some(read_mp3(path)),
@@ -99,6 +100,17 @@ fn read_mp3(path: &Path) -> Result<SongTags> {
 	Ok(song_tags)
 }
 
+fn read_aiff(path: &Path) -> Result<SongTags> {
+	let tag = id3::Tag::read_from_aiff(&path).or_else(|error| {
+		if let Some(tag) = error.partial_tag {
+			Ok(tag)
+		} else {
+			Err(error)
+		}
+	})?;
+	Ok(tag.into())
+}
+
 fn read_wave(path: &Path) -> Result<SongTags> {
 	let tag = id3::Tag::read_from_wav(&path).or_else(|error| {
 		if let Some(tag) = error.partial_tag {
@@ -299,6 +311,10 @@ fn reads_file_metadata() {
 		duration: Some(0),
 		..sample_tags.clone()
 	};
+	assert_eq!(
+		read(Path::new("test-data/formats/sample.aif")).unwrap(),
+		sample_tags
+	);
 	assert_eq!(
 		read(Path::new("test-data/formats/sample.mp3")).unwrap(),
 		mp3_sample_tag
@@ -331,6 +347,11 @@ fn reads_file_metadata() {
 
 #[test]
 fn reads_embedded_artwork() {
+	assert!(
+		read(Path::new("test-data/artwork/sample.aif"))
+			.unwrap()
+			.has_artwork
+	);
 	assert!(
 		read(Path::new("test-data/artwork/sample.mp3"))
 			.unwrap()
diff --git a/src/app/thumbnail/read.rs b/src/app/thumbnail/read.rs
index d2470d5..d47694a 100644
--- a/src/app/thumbnail/read.rs
+++ b/src/app/thumbnail/read.rs
@@ -7,6 +7,7 @@ use crate::utils::AudioFormat;
 
 pub fn read(image_path: &Path) -> Result<DynamicImage> {
 	match utils::get_audio_format(image_path) {
+		Some(AudioFormat::AIFF) => read_aiff(image_path),
 		Some(AudioFormat::APE) => read_ape(image_path),
 		Some(AudioFormat::FLAC) => read_flac(image_path),
 		Some(AudioFormat::MP3) => read_mp3(image_path),
@@ -44,6 +45,12 @@ fn read_mp3(path: &Path) -> Result<DynamicImage> {
 	read_id3(&path, &tag)
 }
 
+fn read_aiff(path: &Path) -> Result<DynamicImage> {
+	let tag = id3::Tag::read_from_aiff(path)?;
+
+	read_id3(&path, &tag)
+}
+
 fn read_wave(path: &Path) -> Result<DynamicImage> {
 	let tag = id3::Tag::read_from_wav(path)?;
 
@@ -99,6 +106,11 @@ fn can_read_artwork_data() {
 		.to_rgb8();
 	assert_eq!(folder_img, ext_img);
 
+	let aiff_img = read(Path::new("test-data/artwork/sample.aif"))
+		.unwrap()
+		.to_rgb8();
+	assert_eq!(aiff_img, embedded_img);
+
 	let ape_img = read(Path::new("test-data/artwork/sample.ape"))
 		.map(|d| d.to_rgb8())
 		.ok();
diff --git a/src/utils.rs b/src/utils.rs
index d745db2..818ce4a 100644
--- a/src/utils.rs
+++ b/src/utils.rs
@@ -14,6 +14,7 @@ pub use crate::match_ignore_case;
 
 #[derive(Debug, PartialEq)]
 pub enum AudioFormat {
+	AIFF,
 	APE,
 	FLAC,
 	MP3,
@@ -34,6 +35,8 @@ pub fn get_audio_format(path: &Path) -> Option<AudioFormat> {
 		_ => return None,
 	};
 	match extension.to_lowercase().as_str() {
+		"aif" => Some(AudioFormat::AIFF),
+		"aiff" => Some(AudioFormat::AIFF),
 		"ape" => Some(AudioFormat::APE),
 		"flac" => Some(AudioFormat::FLAC),
 		"mp3" => Some(AudioFormat::MP3),
@@ -49,6 +52,14 @@ pub fn get_audio_format(path: &Path) -> Option<AudioFormat> {
 #[test]
 fn can_guess_audio_format() {
 	assert_eq!(get_audio_format(Path::new("animals/🐷/my🐖file.jpg")), None);
+	assert_eq!(
+		get_audio_format(Path::new("animals/🐷/my🐖file.aif")),
+		Some(AudioFormat::AIFF)
+	);
+	assert_eq!(
+		get_audio_format(Path::new("animals/🐷/my🐖file.aiff")),
+		Some(AudioFormat::AIFF)
+	);
 	assert_eq!(
 		get_audio_format(Path::new("animals/🐷/my🐖file.flac")),
 		Some(AudioFormat::FLAC)
diff --git a/test-data/artwork/sample.aif b/test-data/artwork/sample.aif
new file mode 100644
index 0000000..42e9ad1
Binary files /dev/null and b/test-data/artwork/sample.aif differ
diff --git a/test-data/formats/sample.aif b/test-data/formats/sample.aif
new file mode 100644
index 0000000..8e1d434
Binary files /dev/null and b/test-data/formats/sample.aif differ