E: Version '1.2.3' for 'curl' was not found means no configured feed offers that exact version string. List the versions apt can see with apt-cache madison curl and pin one of those, copied character for character: apt-get install -y curl=8.5.0-2ubuntu10.16 worked in the test.

The version string includes the Ubuntu revision. In the test the upstream number on its own, curl=8.5.0, gave the same Version '8.5.0' for 'curl' was not found.

The error

$ apt-get install -y curl=1.2.3
Reading package lists...
Building dependency tree...
Reading state information...
Package curl is not available, but is referred to by another package.
This may mean that the package is missing, has been obsoleted, or
is only available from another source

E: Version '1.2.3' for 'curl' was not found
exit code: 100

The middle lines are misleading: curl was available, as the next step shows. A guessed revision that looked plausible, 8.5.0-2ubuntu10.6, gave the same text with E: Version '8.5.0-2ubuntu10.6' for 'curl' was not found.

Why it happens

The part after = is compared with the version strings in the package lists apt downloaded. Neither 1.2.3 nor 8.5.0-2ubuntu10.6 was among them, so apt returned 100 without installing anything. The real versions were these:

Read madison as one line per feed: the version in the middle column, the feed it comes from on the right. Here 8.5.0-2ubuntu10.16 was listed twice, from noble-updates and from noble-security, and 8.5.0-2ubuntu10 once, from noble. apt-cache policy shows the same two versions and names 8.5.0-2ubuntu10.16 as the Candidate. Copy a string from either list instead of typing it from memory.

$ apt-cache madison curl
      curl | 8.5.0-2ubuntu10.16 | http://archive.ubuntu.com/ubuntu noble-updates/main amd64 Packages
      curl | 8.5.0-2ubuntu10.16 | http://security.ubuntu.com/ubuntu noble-security/main amd64 Packages
      curl | 8.5.0-2ubuntu10 | http://archive.ubuntu.com/ubuntu noble/main amd64 Packages
exit code: 0
$ apt-cache policy curl
curl:
  Installed: (none)
  Candidate: 8.5.0-2ubuntu10.16
  Version table:
     8.5.0-2ubuntu10.16 500
        500 http://archive.ubuntu.com/ubuntu noble-updates/main amd64 Packages
        500 http://security.ubuntu.com/ubuntu noble-security/main amd64 Packages
     8.5.0-2ubuntu10 500
        500 http://archive.ubuntu.com/ubuntu noble/main amd64 Packages
exit code: 0

The fix

$ apt-get install -y curl=8.5.0-2ubuntu10.16 > /tmp/c2.log 2>&1; echo "install exit: $?"; grep -E "^(Setting up curl|Get:.* curl )" /tmp/c2.log
install exit: 0
Get:20 http://archive.ubuntu.com/ubuntu noble-updates/main amd64 curl amd64 8.5.0-2ubuntu10.16 [226 kB]
Setting up curl (8.5.0-2ubuntu10.16) ...
exit code: 0
$ dpkg -l curl | tail -1
ii  curl           8.5.0-2ubuntu10.16 amd64        command line tool for transferring data with URL syntax
exit code: 0

The version copied from madison installed. Picking the older listed version is a different story: apt-get install -y curl=8.5.0-2ubuntu10 was found, but stopped on its library, which apt wanted at the newer version:

$ apt-get install -y curl=8.5.0-2ubuntu10
...
The following packages have unmet dependencies:
 curl : Depends: libcurl4t64 (= 8.5.0-2ubuntu10) but 8.5.0-2ubuntu10.16 is to be installed
E: Unable to correct problems, you have held broken packages.
exit code: 100

Pinning the library it names to the same version in the same command worked. curl was already installed at the newer version by then; in a second container in the same state, the command without the flag stopped with E: Packages were downgraded and -y was used without --allow-downgrades. and exit code 100, so the run that worked used --allow-downgrades:

$ apt-get install -y --allow-downgrades curl=8.5.0-2ubuntu10 libcurl4t64=8.5.0-2ubuntu10 > /tmp/c3.log 2>&1; echo "install exit: $?"; grep -E "^(The following|  |Setting up (curl|libcurl4t64))" /tmp/c3.log
install exit: 0
The following packages will be DOWNGRADED:
  curl libcurl4t64
Setting up libcurl4t64:amd64 (8.5.0-2ubuntu10) ...
Setting up curl (8.5.0-2ubuntu10) ...
exit code: 0

How it was reproduced

The capture was made in an ubuntu:24.04 container (Ubuntu 24.04.5 LTS, apt 2.8.3) on Docker Engine 29.9.3, standing in for Ubuntu in WSL, as root after apt-get update. curl was not installed in the image; each pinned install was attempted, then the versions were listed with apt-cache madison and apt-cache policy.

Frequently asked

How do I see which versions of a package apt can install?
Run apt-cache madison with the package name, or apt-cache policy for the candidate and the version table. In the test both listed 8.5.0-2ubuntu10.16 and 8.5.0-2ubuntu10 for curl.
Why does apt say 'Package is not available, but is referred to by another package' with a version?
In the test it was printed together with Version was not found although curl was available; the requested version string was the problem.
How do I install a specific version with apt-get?
Use apt-get install -y name=version with a version copied from apt-cache madison. curl=8.5.0-2ubuntu10.16 installed in the test.

More decoded errors in the Fixes category. If apt cannot find the package at all, see E: Unable to locate package.