diff --git a/Doc/library/cmdline.rst b/Doc/library/cmdline.rst
index 78fe95a014ff7c..59629b693ba00f 100644
--- a/Doc/library/cmdline.rst
+++ b/Doc/library/cmdline.rst
@@ -24,7 +24,7 @@ The following modules have a command-line interface.
 * :mod:`!idlelib`
 * :ref:`inspect <inspect-module-cli>`
 * :ref:`json <json-commandline>`
-* :mod:`mimetypes`
+* :ref:`mimetypes <mimetypes-cli>`
 * :mod:`pdb`
 * :mod:`pickle`
 * :ref:`pickletools <pickletools-cli>`
diff --git a/Doc/library/mimetypes.rst b/Doc/library/mimetypes.rst
index 514e773359a9aa..5af69455032d71 100644
--- a/Doc/library/mimetypes.rst
+++ b/Doc/library/mimetypes.rst
@@ -191,7 +191,7 @@ An example usage of the module::
 
 .. _mimetypes-objects:
 
-MimeTypes Objects
+MimeTypes objects
 -----------------
 
 The :class:`MimeTypes` class may be useful for applications which may want more
@@ -307,3 +307,97 @@ than one MIME-type database; it provides an interface similar to the one of the
 
       When *strict* is ``True`` (the default), the mapping will be added to the
       official MIME types, otherwise to the non-standard ones.
+
+
+.. _mimetypes-cli:
+
+Command-line usage
+------------------
+
+The :mod:`!mimetypes` module can be executed as a script from the command line.
+
+.. code-block:: sh
+
+   python -m mimetypes [-h] [-e] [-l] type [type ...]
+
+The following options are accepted:
+
+.. program:: mimetypes
+
+.. cmdoption:: -h
+               --help
+
+   Show the help message and exit.
+
+.. cmdoption:: -e
+               --extension
+
+   Guess extension instead of type.
+
+.. cmdoption:: -l
+               --lenient
+
+   Additionally search for some common, but non-standard types.
+
+By default the script converts MIME types to file extensions.
+However, if ``--extension`` is specified,
+it converts file extensions to MIME types.
+
+For each ``type`` entry, the script writes a line into the standard output
+stream. If an unknown type occurs, it writes an error message into the
+standard error stream and exits with the return code ``1``.
+
+
+.. mimetypes-cli-example:
+
+Command-line example
+--------------------
+
+Here are some examples of typical usage of the :mod:`!mimetypes` command-line
+interface:
+
+.. code-block:: console
+
+   $ # get a MIME type by a file name
+   $ python -m mimetypes filename.png
+   type: image/png encoding: None
+
+   $ # get a MIME type by a URL
+   $ python -m mimetypes https://example.com/filename.txt
+   type: text/plain encoding: None
+
+   $ # get a complex MIME type
+   $ python -m mimetypes filename.tar.gz
+   type: application/x-tar encoding: gzip
+
+   $ # get a MIME type for a rare file extension
+   $ python -m mimetypes filename.pict
+   error: unknown extension of filename.pict
+
+   $ # now look in the extended database built into Python
+   $ python -m mimetypes --lenient filename.pict
+   type: image/pict encoding: None
+
+   $ # get a file extension by a MIME type
+   $ python -m mimetypes --extension text/javascript
+   .js
+
+   $ # get a file extension by a rare MIME type
+   $ python -m mimetypes --extension text/xul
+   error: unknown type text/xul
+
+   $ # now look in the extended database again
+   $ python -m mimetypes --extension --lenient text/xul
+   .xul
+
+   $ # try to feed an unknown file extension
+   $ python -m mimetypes filename.sh filename.nc filename.xxx filename.txt
+   type: application/x-sh encoding: None
+   type: application/x-netcdf encoding: None
+   error: unknown extension of filename.xxx
+
+   $ # try to feed an unknown MIME type
+   $ python -m mimetypes --extension audio/aac audio/opus audio/future audio/x-wav
+   .aac
+   .opus
+   error: unknown type audio/future
diff --git a/Doc/whatsnew/3.14.rst b/Doc/whatsnew/3.14.rst
index 6539b23380b6e0..d4bf19a4d66ef3 100644
--- a/Doc/whatsnew/3.14.rst
+++ b/Doc/whatsnew/3.14.rst
@@ -641,6 +641,13 @@ json
 mimetypes
 ---------
 
+* Document the command-line for :mod:`mimetypes`.
+  It now exits with ``1`` on failure instead of ``0``
+  and ``2`` on incorrect command-line parameters instead of ``1``.
+  Also, errors are printed to stderr instead of stdout and their text is made
+  tighter.
+  (Contributed by Oleg Iarygin and Hugo van Kemenade in :gh:`93096`.)
+
 * Add MS and :rfc:`8081` MIME types for fonts:
 
   * Embedded OpenType: ``application/vnd.ms-fontobject``
diff --git a/Lib/mimetypes.py b/Lib/mimetypes.py
index ebad9a9ed27337..6b94fe3c4df756 100644
--- a/Lib/mimetypes.py
+++ b/Lib/mimetypes.py
@@ -670,50 +670,38 @@ def _default_mime_types():
 
 
 def _main():
-    import getopt
+    """Run the mimetypes command-line interface."""
     import sys
-
-    USAGE = """\
-Usage: mimetypes.py [options] type
-
-Options:
-    --help / -h       -- print this message and exit
-    --lenient / -l    -- additionally search of some common, but non-standard
-                         types.
-    --extension / -e  -- guess extension instead of type
-
-More than one type argument may be given.
-"""
-
-    def usage(code, msg=''):
-        print(USAGE)
-        if msg: print(msg)
-        sys.exit(code)
-
-    try:
-        opts, args = getopt.getopt(sys.argv[1:], 'hle',
-                                   ['help', 'lenient', 'extension'])
-    except getopt.error as msg:
-        usage(1, msg)
-
-    strict = 1
-    extension = 0
-    for opt, arg in opts:
-        if opt in ('-h', '--help'):
-            usage(0)
-        elif opt in ('-l', '--lenient'):
-            strict = 0
-        elif opt in ('-e', '--extension'):
-            extension = 1
-    for gtype in args:
-        if extension:
-            guess = guess_extension(gtype, strict)
-            if not guess: print("I don't know anything about type", gtype)
-            else: print(guess)
-        else:
-            guess, encoding = guess_type(gtype, strict)
-            if not guess: print("I don't know anything about type", gtype)
-            else: print('type:', guess, 'encoding:', encoding)
+    from argparse import ArgumentParser
+
+    parser = ArgumentParser(description='map filename extensions to MIME types')
+    parser.add_argument(
+        '-e', '--extension',
+        action='store_true',
+        help='guess extension instead of type'
+    )
+    parser.add_argument(
+        '-l', '--lenient',
+        action='store_true',
+        help='additionally search for common but non-standard types'
+    )
+    parser.add_argument('type', nargs='+', help='a type to search')
+    args = parser.parse_args()
+
+    if args.extension:
+        for gtype in args.type:
+            guess = guess_extension(gtype, not args.lenient)
+            if guess:
+                print(guess)
+            else:
+                sys.exit(f"error: unknown type {gtype}")
+    else:
+        for gtype in args.type:
+            guess, encoding = guess_type(gtype, not args.lenient)
+            if guess:
+                print('type:', guess, 'encoding:', encoding)
+            else:
+                sys.exit(f"error: media type unknown for {gtype}")
 
 
 if __name__ == '__main__':
diff --git a/Lib/test/test_mimetypes.py b/Lib/test/test_mimetypes.py
index bceb5c2fa0eb24..b5d1f50099e16a 100644
--- a/Lib/test/test_mimetypes.py
+++ b/Lib/test/test_mimetypes.py
@@ -3,9 +3,11 @@
 import os
 import sys
 import unittest.mock
+from os import linesep
 
 from test import support
 from test.support import os_helper
+from test.support.script_helper import run_python_until_end
 from platform import win32_edition
 
 try:
@@ -390,50 +392,53 @@ def test__all__(self):
 
 class MimetypesCliTestCase(unittest.TestCase):
 
-    def mimetypes_cmd(self, *args, **kwargs):
-        support.patch(self, sys, "argv", [sys.executable, *args])
-        with support.captured_stdout() as output:
-            mimetypes._main()
-            return output.getvalue().strip()
+    def mimetypes_cmd(cls, *args, **kwargs):
+        result, _ = run_python_until_end('-m', 'mimetypes', *args)
+        return result.rc, result.out.decode(), result.err.decode()
 
     def test_help_option(self):
-        support.patch(self, sys, "argv", [sys.executable, "-h"])
-        with support.captured_stdout() as output:
-            with self.assertRaises(SystemExit) as cm:
-                mimetypes._main()
-
-        self.assertIn("Usage: mimetypes.py", output.getvalue())
-        self.assertEqual(cm.exception.code, 0)
+        retcode, out, err = self.mimetypes_cmd('-h')
+        self.assertEqual(retcode, 0)
+        self.assertStartsWith(out, 'usage: ')
+        self.assertEqual(err, '')
 
     def test_invalid_option(self):
-        support.patch(self, sys, "argv", [sys.executable, "--invalid"])
-        with support.captured_stdout() as output:
-            with self.assertRaises(SystemExit) as cm:
-                mimetypes._main()
-
-        self.assertIn("Usage: mimetypes.py", output.getvalue())
-        self.assertEqual(cm.exception.code, 1)
+        retcode, out, err = self.mimetypes_cmd('--invalid')
+        self.assertEqual(retcode, 2)
+        self.assertEqual(out, '')
+        self.assertStartsWith(err, 'usage: ')
 
     def test_guess_extension(self):
-        eq = self.assertEqual
-
-        extension = self.mimetypes_cmd("-l", "-e", "image/jpg")
-        eq(extension, ".jpg")
+        retcode, out, err = self.mimetypes_cmd('-l', '-e', 'image/jpg')
+        self.assertEqual(retcode, 0)
+        self.assertEqual(out, f'.jpg{linesep}')
+        self.assertEqual(err, '')
 
-        extension = self.mimetypes_cmd("-e", "image/jpg")
-        eq(extension, "I don't know anything about type image/jpg")
+        retcode, out, err = self.mimetypes_cmd('-e', 'image/jpg')
+        self.assertEqual(retcode, 1)
+        self.assertEqual(out, '')
+        self.assertEqual(err, f'error: unknown type image/jpg{linesep}')
 
-        extension = self.mimetypes_cmd("-e", "image/jpeg")
-        eq(extension, ".jpg")
+        retcode, out, err = self.mimetypes_cmd('-e', 'image/jpeg')
+        self.assertEqual(retcode, 0)
+        self.assertEqual(out, f'.jpg{linesep}')
+        self.assertEqual(err, '')
 
     def test_guess_type(self):
-        eq = self.assertEqual
-
-        type_info = self.mimetypes_cmd("-l", "foo.pic")
-        eq(type_info, "type: image/pict encoding: None")
-
-        type_info = self.mimetypes_cmd("foo.pic")
-        eq(type_info, "I don't know anything about type foo.pic")
+        retcode, out, err = self.mimetypes_cmd('-l', 'foo.webp')
+        self.assertEqual(retcode, 0)
+        self.assertEqual(out, f'type: image/webp encoding: None{linesep}')
+        self.assertEqual(err, '')
+
+    @unittest.skipIf(
+        sys.platform == 'darwin',
+        'macOS lists common_types in mime.types thus making them always known'
+    )
+    def test_guess_type_conflicting_with_mimetypes(self):
+        retcode, out, err = self.mimetypes_cmd('foo.pic')
+        self.assertEqual(retcode, 1)
+        self.assertEqual(out, '')
+        self.assertEqual(err, f'error: media type unknown for foo.pic{linesep}')
 
 if __name__ == "__main__":
     unittest.main()
diff --git a/Misc/ACKS b/Misc/ACKS
index da528f8b4ca3a7..2663042c06afd6 100644
--- a/Misc/ACKS
+++ b/Misc/ACKS
@@ -849,6 +849,7 @@ Oleg Höfling
 Robert Hölzl
 Stefan Hölzl
 Catalin Iacob
+Oleg Iarygin
 Mihai Ibanescu
 Ali Ikinci
 Aaron Iles
diff --git a/Misc/NEWS.d/next/Library/2022-05-28-19-41-02.gh-issue-93096.qjUyRG.rst b/Misc/NEWS.d/next/Library/2022-05-28-19-41-02.gh-issue-93096.qjUyRG.rst
new file mode 100644
index 00000000000000..fb9ca441c7e2da
--- /dev/null
+++ b/Misc/NEWS.d/next/Library/2022-05-28-19-41-02.gh-issue-93096.qjUyRG.rst
@@ -0,0 +1,5 @@
+Document the command-line for :mod:`mimetypes`.
+It now exits with ``1`` on failure instead of ``0``
+and ``2`` on incorrect command-line parameters instead of ``1``.
+Also, errors are printed to stderr instead of stdout and their text is made
+tighter. Patch by Oleg Iarygin and Hugo van Kemenade.