MIME Type Reference — Kotlin source
A searchable map of common file extensions to their MIME types - text, image, audio, video, application, font, and multipart. Look up by extension or by type, filter by category, and copy the exact Content-Type string for any format.
This is the Kotlin implementation — the same logic the interactive tool runs, in a shareable, citable form.
// mime-types — Kotlin port of the curated extension ↔ MIME table, ported from
// src/lib/mime-types.ts. Display source for CosmoDev's polyglot tool pages.
//
// The table is an immutable List of 71 entries grouped by the seven top-level
// media types (RFC 2046). Each entry's `type` always equals the top-level
// segment of its own `mime`, so the category filter and the Content-Type
// never disagree.
/** The seven top-level media types a curated entry can belong to. */
enum class MimeCategory { TEXT, IMAGE, AUDIO, VIDEO, APPLICATION, FONT, MULTIPART }
/** One curated extension ↔ MIME mapping (immutable value object). */
data class MimeEntry(
val ext: String, // lowercase, no leading dot (e.g. "json")
val mime: String, // full Content-Type (e.g. "application/json")
val type: MimeCategory, // always the top-level segment of `mime`
val name: String, // human-readable format name (e.g. "JSON")
)
/** Optional constraints — null fields are ignored, mirroring `undefined`. */
data class MimeFilter(
val type: MimeCategory? = null,
val query: String? = null,
)
object MimeTypes {
/** Display order of the categories (used by the UI filter). */
val MIME_CATEGORIES: List<MimeCategory> = MimeCategory.entries
/**
* The curated extension ↔ MIME table. One entry is one (extension, type)
* pair, so an extension with several MIME types (e.g. .js) appears more
* than once, and a MIME with several extensions (e.g. image/jpeg)
* appears once per extension. Values follow IANA / MDN conventions.
*/
val MIME: List<MimeEntry> = listOf(
// ── text ────────────────────────────────────────────────────────
MimeEntry("txt", "text/plain", MimeCategory.TEXT, "Plain text"),
MimeEntry("html", "text/html", MimeCategory.TEXT, "HTML document"),
MimeEntry("htm", "text/html", MimeCategory.TEXT, "HTML document"),
MimeEntry("xhtml", "application/xhtml+xml", MimeCategory.APPLICATION, "XHTML"),
MimeEntry("css", "text/css", MimeCategory.TEXT, "CSS stylesheet"),
MimeEntry("csv", "text/csv", MimeCategory.TEXT, "Comma-separated values"),
MimeEntry("xml", "application/xml", MimeCategory.APPLICATION, "XML document"),
MimeEntry("js", "text/javascript", MimeCategory.TEXT, "JavaScript"),
MimeEntry("js", "application/javascript", MimeCategory.APPLICATION, "JavaScript (legacy)"),
MimeEntry("mjs", "text/javascript", MimeCategory.TEXT, "JavaScript module"),
MimeEntry("json", "application/json", MimeCategory.APPLICATION, "JSON"),
MimeEntry("md", "text/markdown", MimeCategory.TEXT, "Markdown"),
MimeEntry("yaml", "text/yaml", MimeCategory.TEXT, "YAML"),
MimeEntry("yml", "text/yaml", MimeCategory.TEXT, "YAML"),
MimeEntry("ics", "text/calendar", MimeCategory.TEXT, "iCalendar"),
MimeEntry("rtf", "application/rtf", MimeCategory.APPLICATION, "Rich text"),
MimeEntry("tsv", "text/tab-separated-values", MimeCategory.TEXT, "Tab-separated values"),
// ── image ───────────────────────────────────────────────────────
MimeEntry("jpg", "image/jpeg", MimeCategory.IMAGE, "JPEG image"),
MimeEntry("jpeg", "image/jpeg", MimeCategory.IMAGE, "JPEG image"),
MimeEntry("png", "image/png", MimeCategory.IMAGE, "PNG image"),
MimeEntry("gif", "image/gif", MimeCategory.IMAGE, "GIF image"),
MimeEntry("webp", "image/webp", MimeCategory.IMAGE, "WebP image"),
MimeEntry("avif", "image/avif", MimeCategory.IMAGE, "AVIF image"),
MimeEntry("svg", "image/svg+xml", MimeCategory.IMAGE, "SVG image"),
MimeEntry("bmp", "image/bmp", MimeCategory.IMAGE, "Bitmap image"),
MimeEntry("ico", "image/x-icon", MimeCategory.IMAGE, "Icon"),
MimeEntry("tif", "image/tiff", MimeCategory.IMAGE, "TIFF image"),
MimeEntry("tiff", "image/tiff", MimeCategory.IMAGE, "TIFF image"),
MimeEntry("heic", "image/heic", MimeCategory.IMAGE, "HEIC image"),
// ── audio ───────────────────────────────────────────────────────
MimeEntry("mp3", "audio/mpeg", MimeCategory.AUDIO, "MP3 audio"),
MimeEntry("wav", "audio/wav", MimeCategory.AUDIO, "WAV audio"),
MimeEntry("ogg", "audio/ogg", MimeCategory.AUDIO, "Ogg audio"),
MimeEntry("oga", "audio/ogg", MimeCategory.AUDIO, "Ogg audio"),
MimeEntry("flac", "audio/flac", MimeCategory.AUDIO, "FLAC audio"),
MimeEntry("aac", "audio/aac", MimeCategory.AUDIO, "AAC audio"),
MimeEntry("m4a", "audio/mp4", MimeCategory.AUDIO, "M4A audio"),
MimeEntry("weba", "audio/webm", MimeCategory.AUDIO, "WebM audio"),
MimeEntry("mid", "audio/midi", MimeCategory.AUDIO, "MIDI"),
MimeEntry("midi", "audio/midi", MimeCategory.AUDIO, "MIDI"),
// ── video ───────────────────────────────────────────────────────
MimeEntry("mp4", "video/mp4", MimeCategory.VIDEO, "MP4 video"),
MimeEntry("webm", "video/webm", MimeCategory.VIDEO, "WebM video"),
MimeEntry("avi", "video/x-msvideo", MimeCategory.VIDEO, "AVI video"),
MimeEntry("mov", "video/quicktime", MimeCategory.VIDEO, "QuickTime video"),
MimeEntry("mkv", "video/x-matroska", MimeCategory.VIDEO, "Matroska video"),
MimeEntry("mpeg", "video/mpeg", MimeCategory.VIDEO, "MPEG video"),
MimeEntry("mpg", "video/mpeg", MimeCategory.VIDEO, "MPEG video"),
MimeEntry("ogv", "video/ogg", MimeCategory.VIDEO, "Ogg video"),
MimeEntry("m4v", "video/mp4", MimeCategory.VIDEO, "M4V video"),
// ── application ─────────────────────────────────────────────────
MimeEntry("pdf", "application/pdf", MimeCategory.APPLICATION, "PDF document"),
MimeEntry("zip", "application/zip", MimeCategory.APPLICATION, "ZIP archive"),
MimeEntry("gz", "application/gzip", MimeCategory.APPLICATION, "Gzip archive"),
MimeEntry("tar", "application/x-tar", MimeCategory.APPLICATION, "Tar archive"),
MimeEntry("rar", "application/vnd.rar", MimeCategory.APPLICATION, "RAR archive"),
MimeEntry("7z", "application/x-7z-compressed", MimeCategory.APPLICATION, "7-Zip archive"),
MimeEntry("bin", "application/octet-stream", MimeCategory.APPLICATION, "Binary data"),
MimeEntry("exe", "application/x-msdownload", MimeCategory.APPLICATION, "Windows executable"),
MimeEntry("jar", "application/java-archive", MimeCategory.APPLICATION, "Java archive"),
MimeEntry("wasm", "application/wasm", MimeCategory.APPLICATION, "WebAssembly"),
MimeEntry("doc", "application/msword", MimeCategory.APPLICATION, "Word document"),
MimeEntry("docx", "application/vnd.openxmlformats-officedocument.wordprocessingml.document", MimeCategory.APPLICATION, "Word document (OOXML)"),
MimeEntry("xls", "application/vnd.ms-excel", MimeCategory.APPLICATION, "Excel spreadsheet"),
MimeEntry("xlsx", "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet", MimeCategory.APPLICATION, "Excel spreadsheet (OOXML)"),
MimeEntry("ppt", "application/vnd.ms-powerpoint", MimeCategory.APPLICATION, "PowerPoint"),
MimeEntry("pptx", "application/vnd.openxmlformats-officedocument.presentationml.presentation", MimeCategory.APPLICATION, "PowerPoint (OOXML)"),
// ── font ────────────────────────────────────────────────────────
MimeEntry("woff", "font/woff", MimeCategory.FONT, "WOFF font"),
MimeEntry("woff2", "font/woff2", MimeCategory.FONT, "WOFF2 font"),
MimeEntry("ttf", "font/ttf", MimeCategory.FONT, "TrueType font"),
MimeEntry("otf", "font/otf", MimeCategory.FONT, "OpenType font"),
MimeEntry("eot", "application/vnd.ms-fontobject", MimeCategory.APPLICATION, "Embedded OpenType"),
// ── multipart ───────────────────────────────────────────────────
MimeEntry("mht", "multipart/related", MimeCategory.MULTIPART, "MHTML web archive"),
MimeEntry("mhtml", "multipart/related", MimeCategory.MULTIPART, "MHTML web archive"),
)
/** Lowercase an extension and drop a leading dot so ".JSON" == "json". */
fun normalizeExt(ext: String): String =
ext.trim().lowercase().trimStart('.')
/**
* Every entry whose extension matches. The dot is optional and matching
* is case-insensitive, so ".js", "JS", and "js" are equivalent.
* Returns an empty list for an unknown/empty extension.
*/
fun lookupByExt(ext: String): List<MimeEntry> {
val e = normalizeExt(ext)
if (e.isEmpty()) return emptyList()
return MIME.filter { it.ext == e }
}
/**
* Every entry whose MIME matches, case-insensitively, tolerating
* surrounding whitespace. One MIME commonly maps to several extensions
* (image/jpeg → jpg, jpeg), so all are returned. Empty for unknown/empty.
*/
fun lookupByMime(mime: String): List<MimeEntry> {
val m = mime.trim().lowercase()
if (m.isEmpty()) return emptyList()
return MIME.filter { it.mime.lowercase() == m }
}
/**
* Filter the full table by category and/or a free-text query matched
* (case-insensitively) against ext, mime, and name. Omitted options are
* ignored; an empty query returns the category-filtered set unchanged.
* An unknown category value yields nothing (it is not silently coerced).
*/
fun filter(opts: MimeFilter = MimeFilter()): List<MimeEntry> {
val q = (opts.query ?: "").trim().lowercase()
return MIME.filter { e ->
(opts.type == null || e.type == opts.type) &&
(q.isEmpty() || q in e.ext.lowercase() || q in e.mime.lowercase() || q in e.name.lowercase())
}
}
}
fun main() {
MimeTypes.lookupByExt(".JSON").forEach { println(".JSON -> ${it.mime} (${it.name})") }
MimeTypes.lookupByMime("IMAGE/JPEG").forEach { println("image/jpeg -> .${it.ext}") }
println("query \"font\": ${MimeTypes.filter(MimeFilter(query = "font")).size} of ${MimeTypes.MIME.size} entries")
}
Also available in 13 other languages
Every CosmoDev tool ships its pure logic in TypeScript (web) and Go (CLI), with authored implementations in a dozen-plus languages — the same contract, ported. Compare all languages side by side →