diff --git a/hashin.py b/hashin.py
index c1bb79b..1590560 100755
--- a/hashin.py
+++ b/hashin.py
@@ -58,6 +58,11 @@ parser.add_argument(
     help='Verbose output',
     action='store_true',
 )
+parser.add_argument(
+    '--include-prereleases',
+    help='Include pre-releases (off by default)',
+    action='store_true',
+)
 parser.add_argument(
     '-p', '--python-version',
     help='Python version to add wheels for. May be used multiple times.',
@@ -83,6 +88,10 @@ class PackageError(Exception):
     pass
 
 
+class NoVersionsError(Exception):
+    """When there are no valid versions found."""
+
+
 def _verbose(*args):
     print('* ' + ' '.join(args))
 
@@ -127,6 +136,7 @@ def run_single_package(
     algorithm,
     python_versions=None,
     verbose=False,
+    include_prereleases=False,
 ):
     restriction = None
     if ';' in spec:
@@ -143,7 +153,8 @@ def run_single_package(
         version=version,
         verbose=verbose,
         python_versions=python_versions,
-        algorithm=algorithm
+        algorithm=algorithm,
+        include_prereleases=include_prereleases,
     )
     package = data['package']
 
@@ -202,7 +213,7 @@ def amend_requirements_content(requirements, package, new_lines):
     return requirements
 
 
-def get_latest_version(data):
+def get_latest_version(data, include_prereleases):
     """
     Return the version string of what we think is the latest version.
     In the data blob from PyPI there is the info->version key which
@@ -214,11 +225,22 @@ def get_latest_version(data):
         # This feels kinda strange but it has worked for years
         return data['info']['version']
     all_versions = []
+    count_prereleases = 0
     for version in data['releases']:
         v = parse(version)
-        if not v.is_prerelease:
+        if not v.is_prerelease or include_prereleases:
             all_versions.append((v, version))
+        else:
+            count_prereleases += 1
     all_versions.sort(reverse=True)
+    if not all_versions:
+        msg = "Not a single valid version found."
+        if not include_prereleases and count_prereleases:
+            msg += (
+                " But, found {0} pre-releases. Consider running again "
+                "with the --include-prereleases flag."
+            )
+        raise NoVersionsError(msg)
     # return the highest non-pre-release version
     return str(all_versions[0][1])
 
@@ -378,6 +400,7 @@ def get_package_hashes(
     algorithm=DEFAULT_ALGORITHM,
     python_versions=(),
     verbose=False,
+    include_prereleases=False,
 ):
     """
     Gets the hashes for the given package.
@@ -404,7 +427,7 @@ def get_package_hashes(
     """
     data = get_package_data(package, verbose)
     if not version:
-        version = get_latest_version(data)
+        version = get_latest_version(data, include_prereleases)
         assert version
         if verbose:
             _verbose('Latest version for {0} is {1}'.format(
@@ -472,6 +495,7 @@ def main():
             args.algorithm,
             args.python_version,
             verbose=args.verbose,
+            include_prereleases=args.include_prereleases,
         )
     except PackageError as exception:
         print(str(exception), file=sys.stderr)

`hashin black` fails
```
▶ hashin black
Traceback (most recent call last):
  File "/usr/local/bin/hashin", line 11, in <module>
    sys.exit(main())
  File "/usr/local/lib/python3.6/site-packages/hashin.py", line 474, in main
    verbose=args.verbose,
  File "/usr/local/lib/python3.6/site-packages/hashin.py", line 120, in run
    run_single_package(spec, *args, **kwargs)
  File "/usr/local/lib/python3.6/site-packages/hashin.py", line 146, in run_single_package
    algorithm=algorithm
  File "/usr/local/lib/python3.6/site-packages/hashin.py", line 407, in get_package_hashes
    version = get_latest_version(data)
  File "/usr/local/lib/python3.6/site-packages/hashin.py", line 223, in get_latest_version
    return str(all_versions[0][1])
IndexError: list index out of range
```

diff --git a/tests/test_arg_parse.py b/tests/test_arg_parse.py
index 7d00e74..a6b6236 100644
--- a/tests/test_arg_parse.py
+++ b/tests/test_arg_parse.py
@@ -18,6 +18,7 @@ def test_everything():
         requirements_file='reqs.txt',
         verbose=True,
         version=False,
+        include_prereleases=False,
     )
     assert args == (expected, [])
 
@@ -37,6 +38,7 @@ def test_everything_long():
         requirements_file='reqs.txt',
         verbose=True,
         version=False,
+        include_prereleases=False,
     )
     assert args == (expected, [])
 
@@ -50,5 +52,6 @@ def test_minimal():
         requirements_file='requirements.txt',
         verbose=False,
         version=False,
+        include_prereleases=False,
     )
     assert args == (expected, [])
diff --git a/tests/test_cli.py b/tests/test_cli.py
index c0b566f..72cf2de 100644
--- a/tests/test_cli.py
+++ b/tests/test_cli.py
@@ -73,7 +73,10 @@ class Tests(TestCase):
 
     @mock.patch('hashin.urlopen')
     def test_get_latest_version_simple(self, murlopen):
-        version = hashin.get_latest_version({'info': {'version': '0.3'}})
+        version = hashin.get_latest_version(
+            {'info': {'version': '0.3'}},
+            False
+        )
         self.assertEqual(version, '0.3')
 
     @mock.patch('hashin.urlopen')
@@ -91,9 +94,43 @@ class Tests(TestCase):
                 '2.0b2': {},
                 '2.0c3': {},
             }
-        })
+        }, False)
         self.assertEqual(version, '0.999')
 
+    @mock.patch('hashin.urlopen')
+    def test_get_latest_version_only_pre_release(self, murlopen):
+        self.assertRaises(
+            hashin.NoVersionsError,
+            hashin.get_latest_version,
+            {
+                'info': {
+                    'version': '0.3',
+                },
+                'releases': {
+                    '1.1.0rc1': {},
+                    '1.1rc1': {},
+                    '1.0a1': {},
+                    '2.0b2': {},
+                    '2.0c3': {},
+                }
+            },
+            False,
+        )
+
+        version = hashin.get_latest_version({
+            'info': {
+                'version': '0.3',
+            },
+            'releases': {
+                '1.1.0rc1': {},
+                '1.1rc1': {},
+                '1.0a1': {},
+                '2.0b2': {},
+                '2.0c3': {},
+            }
+        }, True)
+        self.assertEqual(version, '2.0c3')
+
     @mock.patch('hashin.urlopen')
     def test_get_latest_version_non_pre_release_leading_zeros(self, murlopen):
         version = hashin.get_latest_version({
@@ -105,7 +142,7 @@ class Tests(TestCase):
                 '0.04.21': {},
                 '0.04.09': {},
             }
-        })
+        }, False)
         self.assertEqual(version, '0.04.21')
 
     @mock.patch('hashin.urlopen')

pip install -e .[dev]
parse_log_pytest
requirements.txt
pytest mock
3.9
pytest --no-header -rA --tb=line --color=no -p no:cacheprovider -W ignore::DeprecationWarning
exceptiongroup==1.2.2
-e git+https://github.com/peterbe/hashin.git@bbe0b6c379e25fbd8d3e702473e8e29677ccd9c0#egg=hashin
iniconfig==2.1.0
mock==5.2.0
packaging==24.2
pip-api==0.0.34
pluggy==1.5.0
pytest==8.3.5
tomli==2.2.1

name: hashin
channels:
  - defaults
  - https://repo.anaconda.com/pkgs/main
  - https://repo.anaconda.com/pkgs/r
  - conda-forge
dependencies:
  - _libgcc_mutex=0.1=main
  - _openmp_mutex=5.1=1_gnu
  - ca-certificates=2025.2.25=h06a4308_0
  - ld_impl_linux-64=2.40=h12ee557_0
  - libffi=3.4.4=h6a678d5_1
  - libgcc-ng=11.2.0=h1234567_1
  - libgomp=11.2.0=h1234567_1
  - libstdcxx-ng=11.2.0=h1234567_1
  - ncurses=6.4=h6a678d5_0
  - openssl=3.0.16=h5eee18b_0
  - pip=25.0=py39h06a4308_0
  - python=3.9.21=he870216_1
  - readline=8.2=h5eee18b_0
  - setuptools=75.8.0=py39h06a4308_0
  - sqlite=3.45.3=h5eee18b_0
  - tk=8.6.14=h39e8969_0
  - tzdata=2025a=h04d1e81_0
  - wheel=0.45.1=py39h06a4308_0
  - xz=5.6.4=h5eee18b_1
  - zlib=1.2.13=h5eee18b_1
  - pip:
      - exceptiongroup==1.2.2
      - iniconfig==2.1.0
      - mock==5.2.0
      - packaging==24.2
      - pip-api==0.0.34
      - pluggy==1.5.0
      - pytest==8.3.5
      - tomli==2.2.1
prefix: /opt/conda/envs/hashin

tests/test_arg_parse.py::test_everything tests/test_arg_parse.py::test_everything_long tests/test_arg_parse.py::test_minimal tests/test_cli.py::Tests::test_get_latest_version_non_pre_release tests/test_cli.py::Tests::test_get_latest_version_non_pre_release_leading_zeros tests/test_cli.py::Tests::test_get_latest_version_only_pre_release tests/test_cli.py::Tests::test_get_latest_version_simple
tests/test_cli.py::Tests::test_amend_requirements_content_new tests/test_cli.py::Tests::test_amend_requirements_content_new_similar_name tests/test_cli.py::Tests::test_amend_requirements_content_replacement tests/test_cli.py::Tests::test_amend_requirements_content_replacement_2 tests/test_cli.py::Tests::test_amend_requirements_content_replacement_amonst_others tests/test_cli.py::Tests::test_amend_requirements_content_replacement_amonst_others_2 tests/test_cli.py::Tests::test_amend_requirements_content_replacement_single_to_multi tests/test_cli.py::Tests::test_expand_python_version tests/test_cli.py::Tests::test_filter_releases tests/test_cli.py::Tests::test_get_hashes_error tests/test_cli.py::Tests::test_get_package_hashes tests/test_cli.py::Tests::test_get_package_hashes_unknown_algorithm tests/test_cli.py::Tests::test_get_package_hashes_without_version tests/test_cli.py::Tests::test_main_packageerrors_stderr tests/test_cli.py::Tests::test_main_version tests/test_cli.py::Tests::test_non_200_ok_download tests/test_cli.py::Tests::test_release_url_metadata_python tests/test_cli.py::Tests::test_run tests/test_cli.py::Tests::test_run_case_insensitive tests/test_cli.py::Tests::test_run_contained_names tests/test_cli.py::Tests::test_run_pep_0496 tests/test_cli.py::Tests::test_run_without_specific_version
hashin.py
hashin.py