Skip to content

MIME Type Reference — Go 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 Go implementation — the same logic the interactive tool runs, in a shareable, citable form.

// Package mimetypes is the Go twin of CosmoDev's src/lib/mime-types.ts (dual
// source: the web lib is TypeScript, the CLI lib is Go — kept in lock-step).
// Pure + deterministic, never panics. The table-driven tests in
// mime-types_test.go share vectors with src/lib/mime-types.test.ts so the two
// implementations are held to the same contract.
//
// The package exposes a curated extension ↔ MIME table grouped by the seven
// top-level media types (RFC 2046) — text, image, audio, video, application,
// font, multipart — plus case-insensitive extension/MIME lookups and a
// category+query filter. The Type field always equals the top-level segment of
// the entry's own Mime string, so the category filter and the Content-Type
// never disagree (the data-integrity test enforces this invariant).
package mimetypes

import "strings"

// Category is one of the seven top-level media types a curated entry can belong
// to. It mirrors the MimeCategory union in the TS lib.
type Category string

const (
	CatText        Category = "text"
	CatImage       Category = "image"
	CatAudio       Category = "audio"
	CatVideo       Category = "video"
	CatApplication Category = "application"
	CatFont        Category = "font"
	CatMultipart   Category = "multipart"
)

// MIMECategories is the display order of the categories (used by the UI filter).
// Mirrors MIME_CATEGORIES in the TS lib.
var MIMECategories = []Category{
	CatText,
	CatImage,
	CatAudio,
	CatVideo,
	CatApplication,
	CatFont,
	CatMultipart,
}

// MimeEntry is one row of the extension ↔ MIME table. It mirrors the MimeEntry
// interface in the TS lib.
type MimeEntry struct {
	// Ext is the file extension, lowercase, no leading dot (e.g. "json").
	Ext string
	// Mime is the full MIME / Content-Type string (e.g. "application/json").
	Mime string
	// Type is the top-level media type — matches the Mime string's first segment.
	Type Category
	// Name is a human-readable format name (e.g. "JSON").
	Name string
}

// MIME is the curated extension ↔ MIME table. One entry is one (extension,
// type) pair, so a single extension with several MIME types (e.g. .js) appears
// more than once, and a single MIME with several extensions (e.g. image/jpeg)
// appears once per extension. MIME values follow IANA / MDN conventions.
// Mirrors MIME in the TS lib.
var MIME = []MimeEntry{
	// ── text ──────────────────────────────────────────────────────────────
	{Ext: "txt", Mime: "text/plain", Type: "text", Name: "Plain text"},
	{Ext: "html", Mime: "text/html", Type: "text", Name: "HTML document"},
	{Ext: "htm", Mime: "text/html", Type: "text", Name: "HTML document"},
	{Ext: "xhtml", Mime: "application/xhtml+xml", Type: "application", Name: "XHTML"},
	{Ext: "css", Mime: "text/css", Type: "text", Name: "CSS stylesheet"},
	{Ext: "csv", Mime: "text/csv", Type: "text", Name: "Comma-separated values"},
	{Ext: "xml", Mime: "application/xml", Type: "application", Name: "XML document"},
	{Ext: "js", Mime: "text/javascript", Type: "text", Name: "JavaScript"},
	{Ext: "js", Mime: "application/javascript", Type: "application", Name: "JavaScript (legacy)"},
	{Ext: "mjs", Mime: "text/javascript", Type: "text", Name: "JavaScript module"},
	{Ext: "json", Mime: "application/json", Type: "application", Name: "JSON"},
	{Ext: "md", Mime: "text/markdown", Type: "text", Name: "Markdown"},
	{Ext: "yaml", Mime: "text/yaml", Type: "text", Name: "YAML"},
	{Ext: "yml", Mime: "text/yaml", Type: "text", Name: "YAML"},
	{Ext: "ics", Mime: "text/calendar", Type: "text", Name: "iCalendar"},
	{Ext: "rtf", Mime: "application/rtf", Type: "application", Name: "Rich text"},
	{Ext: "tsv", Mime: "text/tab-separated-values", Type: "text", Name: "Tab-separated values"},

	// ── image ─────────────────────────────────────────────────────────────
	{Ext: "jpg", Mime: "image/jpeg", Type: "image", Name: "JPEG image"},
	{Ext: "jpeg", Mime: "image/jpeg", Type: "image", Name: "JPEG image"},
	{Ext: "png", Mime: "image/png", Type: "image", Name: "PNG image"},
	{Ext: "gif", Mime: "image/gif", Type: "image", Name: "GIF image"},
	{Ext: "webp", Mime: "image/webp", Type: "image", Name: "WebP image"},
	{Ext: "avif", Mime: "image/avif", Type: "image", Name: "AVIF image"},
	{Ext: "svg", Mime: "image/svg+xml", Type: "image", Name: "SVG image"},
	{Ext: "bmp", Mime: "image/bmp", Type: "image", Name: "Bitmap image"},
	{Ext: "ico", Mime: "image/x-icon", Type: "image", Name: "Icon"},
	{Ext: "tif", Mime: "image/tiff", Type: "image", Name: "TIFF image"},
	{Ext: "tiff", Mime: "image/tiff", Type: "image", Name: "TIFF image"},
	{Ext: "heic", Mime: "image/heic", Type: "image", Name: "HEIC image"},

	// ── audio ─────────────────────────────────────────────────────────────
	{Ext: "mp3", Mime: "audio/mpeg", Type: "audio", Name: "MP3 audio"},
	{Ext: "wav", Mime: "audio/wav", Type: "audio", Name: "WAV audio"},
	{Ext: "ogg", Mime: "audio/ogg", Type: "audio", Name: "Ogg audio"},
	{Ext: "oga", Mime: "audio/ogg", Type: "audio", Name: "Ogg audio"},
	{Ext: "flac", Mime: "audio/flac", Type: "audio", Name: "FLAC audio"},
	{Ext: "aac", Mime: "audio/aac", Type: "audio", Name: "AAC audio"},
	{Ext: "m4a", Mime: "audio/mp4", Type: "audio", Name: "M4A audio"},
	{Ext: "weba", Mime: "audio/webm", Type: "audio", Name: "WebM audio"},
	{Ext: "mid", Mime: "audio/midi", Type: "audio", Name: "MIDI"},
	{Ext: "midi", Mime: "audio/midi", Type: "audio", Name: "MIDI"},

	// ── video ─────────────────────────────────────────────────────────────
	{Ext: "mp4", Mime: "video/mp4", Type: "video", Name: "MP4 video"},
	{Ext: "webm", Mime: "video/webm", Type: "video", Name: "WebM video"},
	{Ext: "avi", Mime: "video/x-msvideo", Type: "video", Name: "AVI video"},
	{Ext: "mov", Mime: "video/quicktime", Type: "video", Name: "QuickTime video"},
	{Ext: "mkv", Mime: "video/x-matroska", Type: "video", Name: "Matroska video"},
	{Ext: "mpeg", Mime: "video/mpeg", Type: "video", Name: "MPEG video"},
	{Ext: "mpg", Mime: "video/mpeg", Type: "video", Name: "MPEG video"},
	{Ext: "ogv", Mime: "video/ogg", Type: "video", Name: "Ogg video"},
	{Ext: "m4v", Mime: "video/mp4", Type: "video", Name: "M4V video"},

	// ── application ───────────────────────────────────────────────────────
	{Ext: "pdf", Mime: "application/pdf", Type: "application", Name: "PDF document"},
	{Ext: "zip", Mime: "application/zip", Type: "application", Name: "ZIP archive"},
	{Ext: "gz", Mime: "application/gzip", Type: "application", Name: "Gzip archive"},
	{Ext: "tar", Mime: "application/x-tar", Type: "application", Name: "Tar archive"},
	{Ext: "rar", Mime: "application/vnd.rar", Type: "application", Name: "RAR archive"},
	{Ext: "7z", Mime: "application/x-7z-compressed", Type: "application", Name: "7-Zip archive"},
	{Ext: "bin", Mime: "application/octet-stream", Type: "application", Name: "Binary data"},
	{Ext: "exe", Mime: "application/x-msdownload", Type: "application", Name: "Windows executable"},
	{Ext: "jar", Mime: "application/java-archive", Type: "application", Name: "Java archive"},
	{Ext: "wasm", Mime: "application/wasm", Type: "application", Name: "WebAssembly"},
	{Ext: "doc", Mime: "application/msword", Type: "application", Name: "Word document"},
	{Ext: "docx", Mime: "application/vnd.openxmlformats-officedocument.wordprocessingml.document", Type: "application", Name: "Word document (OOXML)"},
	{Ext: "xls", Mime: "application/vnd.ms-excel", Type: "application", Name: "Excel spreadsheet"},
	{Ext: "xlsx", Mime: "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet", Type: "application", Name: "Excel spreadsheet (OOXML)"},
	{Ext: "ppt", Mime: "application/vnd.ms-powerpoint", Type: "application", Name: "PowerPoint"},
	{Ext: "pptx", Mime: "application/vnd.openxmlformats-officedocument.presentationml.presentation", Type: "application", Name: "PowerPoint (OOXML)"},

	// ── font ──────────────────────────────────────────────────────────────
	{Ext: "woff", Mime: "font/woff", Type: "font", Name: "WOFF font"},
	{Ext: "woff2", Mime: "font/woff2", Type: "font", Name: "WOFF2 font"},
	{Ext: "ttf", Mime: "font/ttf", Type: "font", Name: "TrueType font"},
	{Ext: "otf", Mime: "font/otf", Type: "font", Name: "OpenType font"},
	{Ext: "eot", Mime: "application/vnd.ms-fontobject", Type: "application", Name: "Embedded OpenType"},

	// ── multipart ─────────────────────────────────────────────────────────
	{Ext: "mht", Mime: "multipart/related", Type: "multipart", Name: "MHTML web archive"},
	{Ext: "mhtml", Mime: "multipart/related", Type: "multipart", Name: "MHTML web archive"},
}

// MimeFilter constrains the table by top-level category and/or a free-text
// query. It mirrors the MimeFilter interface in the TS lib. The zero value
// (MimeFilter{}) matches the TS default (filter() with no options): no category
// constraint and no query, returning the whole table.
type MimeFilter struct {
	// Type constrains the result to a single top-level category. The zero value
	// "" means any category (matching an omitted opts.type in the TS lib). An
	// unknown category value yields nothing — it is not silently coerced.
	Type Category
	// Query is free text matched case-insensitively against Ext, Mime, and Name.
	// The zero value "" means no query.
	Query string
}

// NormalizeExt lowercases an extension and drops a leading dot (and surrounding
// whitespace) so ".JSON" and "json" match. It mirrors normalizeExt() in the TS
// lib. Returns "" for empty or dot-only input.
func NormalizeExt(ext string) string {
	return strings.TrimLeft(strings.ToLower(strings.TrimSpace(ext)), ".")
}

// LookupByExt finds every entry whose extension matches. The dot is optional
// and matching is case-insensitive, so LookupByExt(".js"), LookupByExt("JS"),
// and LookupByExt("js") are equivalent. It returns an empty (nil) slice for an
// unknown/empty ext. Mirrors lookupByExt() in the TS lib.
func LookupByExt(ext string) []MimeEntry {
	e := NormalizeExt(ext)
	var out []MimeEntry
	if e == "" {
		return out
	}
	for _, m := range MIME {
		if m.Ext == e {
			out = append(out, m)
		}
	}
	return out
}

// LookupByMime finds every entry whose MIME type matches, case-insensitively
// (also tolerating surrounding whitespace). One MIME commonly maps to several
// extensions — e.g. image/jpeg → jpg, jpeg — so all are returned. It returns an
// empty (nil) slice for unknown/empty input. Mirrors lookupByMime() in the TS lib.
func LookupByMime(mime string) []MimeEntry {
	m := strings.ToLower(strings.TrimSpace(mime))
	var out []MimeEntry
	if m == "" {
		return out
	}
	for _, e := range MIME {
		if strings.ToLower(e.Mime) == m {
			out = append(out, e)
		}
	}
	return out
}

// Filter filters the full table by category and/or a free-text query. The zero
// value Filter(MimeFilter{}) returns the whole table. An unknown category value
// yields nothing (it is not silently coerced). Mirrors filter() in the TS lib.
func Filter(opts MimeFilter) []MimeEntry {
	q := strings.ToLower(strings.TrimSpace(opts.Query))
	var out []MimeEntry
	for _, e := range MIME {
		if opts.Type != "" && e.Type != opts.Type {
			continue
		}
		if q != "" {
			if !(strings.Contains(strings.ToLower(e.Ext), q) ||
				strings.Contains(strings.ToLower(e.Mime), q) ||
				strings.Contains(strings.ToLower(e.Name), q)) {
				continue
			}
		}
		out = append(out, e)
	}
	return out
}

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 →