Two-lens system image position calculator
This two-lens system image position calculator follows light through two separated thin lenses using the standard paraxial sign convention.
Run — free
It first finds the image made by lens one, converts that location into the signed object distance for lens two, and then calculates the final image. The result includes positions relative to both lenses, total transverse magnification, whether the final image is real or virtual, and whether it is upright or inverted. All distances use meters, and focal lengths may represent converging or diverging lenses.
Describe both lenses with one consistent coordinate system
Enter the signed focal length of each thin lens, the positive distance from the original object to the first lens, and the positive separation between the lenses. A converging lens has a positive focal length, while a diverging lens has a negative focal length. The calculator places lens one at coordinate zero and lens two at the separation coordinate, with light traveling from lens one toward lens two. The original object is therefore a real object on the incoming side of lens one. Keeping every length in meters avoids hidden conversions and makes the returned positions directly comparable. The thin-lens and paraxial assumptions matter: lens thickness is neglected, both lenses share an optical axis, and rays make small angles with that axis. This model is appropriate for classroom ray diagrams, preliminary bench layouts, and first-order optical design. It is not a substitute for thick-lens principal planes, aberration analysis, aperture stops, or wavelength-dependent glass data when those effects materially influence a real instrument.
Follow the intermediate image into the second calculation
The first calculation applies the thin-lens equation to lens one and returns its signed image distance. That image location is then compared with the position of lens two. The signed object distance for lens two equals the lens separation minus the first image distance. If the intermediate image lies to the left of lens two, this distance is positive and lens two receives a real object. If lens one would bring the rays to a focus beyond lens two, the distance is negative: lens two intercepts converging rays and receives a virtual object. This sign change is the central detail that makes a two-lens problem different from two unrelated single-lens calculations. The calculator then applies the same thin-lens equation to lens two. A positive final image distance indicates a real final image on the outgoing side of lens two; a negative value indicates a virtual final image on its incoming side. It also adds the separation to report the final coordinate measured from lens one.
Interpret image position, magnification, and singular cases
Use the final distance from lens two when placing a screen, sensor, or observation plane relative to the second element. Use the final position from lens one when your mechanical drawing has its origin at the first lens. Total transverse magnification is the product of the magnifications produced by the two imaging stages. Its absolute value gives the image-size ratio in this ideal model, while its sign determines orientation: a negative result is inverted and a positive result is upright relative to the original object. The real or virtual label is based on the signed final image distance, not on orientation. Certain exact configurations do not have a finite image position. An object at the focal plane of lens one sends collimated light onward, and an object at the focal plane of lens two produces a final image at infinity. The calculator reports these as invalid finite-position requests rather than returning a non-JSON infinity. It likewise rejects zero focal lengths, nonpositive geometry distances, nonfinite values, and the degenerate case where the intermediate image falls exactly in the second lens plane.
What you can do with it
Place a camera sensor behind a relay lens pair
Estimate the signed sensor location after an objective and relay lens before refining the design with a full optical model.
Check a physics homework ray diagram
Verify the intermediate object convention, final image position, orientation, and total magnification for a two-lens exercise.
Explore converging and diverging combinations
Compare how focal-length signs and lens spacing change whether the second lens receives a real or virtual object.
FAQ
Which sign convention does the calculator use?
It uses 1/f = 1/do + 1/di. Real objects and real outgoing images have positive distances; virtual objects and virtual images have negative distances.
Can either lens be diverging?
Yes. Enter a negative focal length for a diverging lens and a positive focal length for a converging lens.
Why can the second object distance be negative?
It is negative when the first lens would form its image beyond the second lens, so the second lens receives converging rays associated with a virtual object.
What does the final position from the first lens mean?
It is the coordinate of the final image when lens one is at zero and lens two is at the positive lens-separation coordinate.
What happens when an image is at infinity?
The request returns an invalid-input error because infinity is not a finite physical placement or a valid JSON number.
How much does an API calculation cost?
Each API calculation costs $0.002. The browser calculator uses the same deterministic formulas.
For developers — API access
Everything on this page is available programmatically. This section is for teams who want to wire it into their own systems; everyone else can just use the tool above.
API endpoint
Prefer to automate it? One authenticated POST creates the task; the result comes back by webhook or a signed link. The same capability also runs here on the web, by email and from Telegram — and soon from our app too.
Call it from your stack
curl -X POST https://api.kit.forhosting.com/optics/two-lens-system-image \
-H "Authorization: Bearer $KIT_KEY" \
-H "Content-Type: application/json" \
-d '{"focal_length_1":0.1,"focal_length_2":0.2,"object_distance":0.3,"lens_separation":0.5}'const res = await fetch("https://api.kit.forhosting.com/optics/two-lens-system-image", {
method: "POST",
headers: {
"Authorization": `Bearer ${process.env.KIT_KEY}`,
"Content-Type": "application/json"
},
body: JSON.stringify({
"focal_length_1": 0.1,
"focal_length_2": 0.2,
"object_distance": 0.3,
"lens_separation": 0.5
})
});
const { task_id } = await res.json();import os, requests
res = requests.post(
"https://api.kit.forhosting.com/optics/two-lens-system-image",
headers={"Authorization": f"Bearer {os.environ['KIT_KEY']}"},
json={
"focal_length_1": 0.1,
"focal_length_2": 0.2,
"object_distance": 0.3,
"lens_separation": 0.5
},
)
task_id = res.json()["task_id"]<?php
$res = file_get_contents("https://api.kit.forhosting.com/optics/two-lens-system-image", false, stream_context_create([
"http" => [
"method" => "POST",
"header" => "Authorization: Bearer " . getenv("KIT_KEY") . "\r\nContent-Type: application/json",
"content" => '{"focal_length_1":0.1,"focal_length_2":0.2,"object_distance":0.3,"lens_separation":0.5}',
],
]));
$task = json_decode($res, true);body := bytes.NewBufferString(`{"focal_length_1":0.1,"focal_length_2":0.2,"object_distance":0.3,"lens_separation":0.5}`)
req, _ := http.NewRequest("POST", "https://api.kit.forhosting.com/optics/two-lens-system-image", body)
req.Header.Set("Authorization", "Bearer "+os.Getenv("KIT_KEY"))
req.Header.Set("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)Example request
{
"focal_length_1": 0.1,
"focal_length_2": 0.2,
"object_distance": 0.3,
"lens_separation": 0.5
}Example response
{
"task_id": "tsk_a1b2c3d4e5f6a1b2c3d4e5f6",
"type": "optics.two_lens_system_image",
"status": "queued",
"_links": {
"result": "/tasks/tsk_…/result"
}
}The API is asynchronous: the call returns a task_id immediately and the result arrives by webhook. Polling is capped at 1 req/s per task.
Pricing
Published price — no tokens, no invented credits. A failed task is never charged.
Errors
| HTTP | Code | Meaning |
|---|---|---|
401 | unauthorized | Missing or invalid API key. |
402 | insufficient_balance | Your balance doesn't cover the task price. |
404 | unknown_type | That task type doesn't exist. |
429 | rate_limited | Too many requests. Use the webhook instead of polling. |