Trust

How the calculations on this site are made

VedicBirth14 min read

In short

Positions come from the Swiss Ephemeris on JPL DE441 data files, sidereal with the Lahiri ayanamsha, using whole-sign houses and the mean node for Rahu and Ketu. Birth times use the birth place's timezone and its historical offset; if the chart has no usable coordinates, the account's timezone, then Asia/Kolkata.

Anyone can assert a planetary position. Stating how it was arrived at is what makes it checkable, so these are the conventions this site uses, held constant across every chart and every reading. Where one is weaker than you might expect, it is written that way on purpose: a settings list that flatters the engine is worth nothing to someone trying to reproduce a chart. The page has been corrected several times; each correction is dated in the history at the bottom.

The settings at a glance

settingwhat we use
EphemerisSwiss Ephemeris 2.10.03 on the compressed JPL DE441 data files, covering 1800 to 2399; their names and digests are under "Run it yourself"
Python bindingpyswisseph==2.10.3.2, the package that carries that Swiss Ephemeris version
Python3.13, in the python:3.13-slim server image; the patch release is not recorded on this page
Calculation flagsPlanets: FLG_SWIEPH, FLG_SPEED and FLG_SIDEREAL; ascendant: FLG_SWIEPH and FLG_SIDEREAL. Apparent, geocentric positions, with the library's own conversion from UT to ephemeris time
ZodiacSidereal, Lahiri (Chitrapaksha) ayanamsha: SIDM_LAHIRI, 23°15′00.658″ at 21 March 1956, 0:00 TDT, a true value that includes nutation
HousesWhole sign
Lunar nodesMean node for Rahu, Ketu exactly 180 degrees from it
TimezoneThe birth place's IANA zone, looked up from the coordinates with timezonefinder 9.0.0; if the chart has no usable coordinates, the timezone on your account, then Asia/Kolkata
Timezone dataPython's zoneinfo, which applies the IANA rules in force on the birth date, from the copy of the database the server supplies; its release is not recorded on this page
CoordinatesA place search against Photon, restricted to features carrying OpenStreetMap's place tag, with no filter on the type of place: the single point Photon returns for the place you choose; the date of Photon's data is not recorded on this page
RoundingNone: full double precision, rounded only where a number is shown
Birth time and placewhat you give usTimezone of the birth placeIANA offset, else two fallbacksOne instant in UTCno rounding, no nudgingSwiss Ephemeris, DE441 datatropical longitude of each bodyLahiri ayanamsha removedsidereal longitudeWhole sign houses, nakshatra, padathe chart you are shown
Six stages between your birth certificate and your chart, and each is somewhere an error can enter. The sections below record the settings that govern them.

Positions

Planetary positions come from the Swiss Ephemeris running the compressed data files derived from NASA JPL's DE441. The version and the years they cover are in the settings table.

Swiss Ephemeris can also run from an analytical ephemeris built into the library, originally by Steve Moshier, and it falls back to it silently when the data files are absent. We ran that way without knowing until 13 September 2026. The two agree closely, and here is how closely, measured rather than assumed:

planetworst disagreement
Moon2.73 arcseconds
Mars0.99
Jupiter0.78
Saturn0.64
Venus0.50
Mercury0.15
Sun0.10

A pada, the smallest division this site works in, is 12,000 arcseconds wide, so the worst case is about one part in four thousand of a pada.

That does not prove no chart was affected, so we tested the thing itself: which division each ephemeris placed each body in, across 48,000 sampled positions.

divisiondisagreements
sign0 of 48,000
nakshatra0 of 48,000
pada1 of 48,000

So it is not never: one sampled position in 48,000 sat close enough to a pada boundary for the two to disagree. One event is too few to give a rate with any confidence. What it does not tell you is whether it happened in a chart we served: a rate in a sample is not an event in a population, and we have not audited the charts we actually served. We will not quote a number for them we have not measured, in either direction.

Reproducing those two tables

Both runs use swe.set_sid_mode(swe.SIDM_LAHIRI) and compare FLG_SWIEPH | FLG_SIDEREAL against FLG_MOSEPH | FLG_SIDEREAL, on the pyswisseph version named in the settings table.

  • The arcsecond table: start at Julian Day for 1 January 1900, 12:00 UT, step 36.7 days, 2,000 dates, seven bodies from Sun to Saturn.
  • The division table: same start, step 12.2 days, 6,000 dates, eight bodies, the same seven plus the mean node. 6,000 times 8 is the 48,000.

Run those and you should get these numbers. If you do not, we would like to know.

Calculation flags

Planet longitudes come from swe.calc_ut with FLG_SWIEPH, FLG_SPEED and FLG_SIDEREAL, and the ascendant from swe.houses_ex with FLG_SWIEPH and FLG_SIDEREAL, with the sidereal mode set to SIDM_LAHIRI. FLG_SPEED only adds the daily speed, which is used for the retrograde marker; the longitude is the same number with or without it, which is why the script in "Run it yourself" leaves it out.

None of the flags that change the default kind of position is set: not FLG_TRUEPOS, FLG_NOABERR, FLG_NOGDEFL, FLG_TOPOCTR or FLG_HELCTR. The Swiss Ephemeris programming documentation says the default is an apparent position in geocentric ecliptic coordinates, relative to the true equinox of the date (section 3.3.1). Apparent means corrected for the light-time from the body to the Earth, and geocentric means seen from the centre of the Earth rather than from the birth place (section 3.3.5, "True or apparent positions"). FLG_SIDEREAL then refers the longitude to the Lahiri zero point instead of the equinox of the date. For the mean node, a mathematical point, the manual says there is no apparent position and that its true position is returned (section 3.3.1); this is the mean node still, not the true node.

calc_ut takes the Julian day in UT, and the library converts it to ephemeris time itself (section 3.1). Our chart code calls no delta-T function and sets no delta-T value of its own.

Sidereal frame

Calculations are sidereal, using the Lahiri (Chitrapaksha) ayanamsha, SIDM_LAHIRI in Swiss Ephemeris terms: the modern realization, with its value at 21 March 1956 in the settings table, not the 23°15′00″ the Calendar Reform Committee fixed for 21 March 1956, which Swiss Ephemeris keeps separately as SIDM_LAHIRI_ICRC. The Swiss Ephemeris documentation, section 2.8.5 and Appendix E, attributes the settings-table value to the Indian Astronomical Ephemeris from 1985 and says it is a true ayanamsha, one that includes nutation. The library holds the mean value, 23°14′44″ at 21 March 1956, and adds nutation when it converts to sidereal longitudes; "Run it yourself" prints both values.

Tropical zerovernal equinoxLahiri zero23°15′00.658″at 21 March 1956grows ~50″/year(Committee item 7)
Two zero points on the ecliptic, plotted on one axis: cream marks the tropical zero point (the vernal equinox), gold the Lahiri zero point at the settings-table epoch. The dashed arrow shows the direction the gap between them moves, at the rate the Calendar Reform Committee's item 7 gives for its own variable ayanamsha; it carries no end value, because this page has not computed the ayanamsha at any date but the check case's.

In the Report of the Calendar Reform Committee (Council of Scientific and Industrial Research, New Delhi, 1955; chairman M. N. Saha), the recommendations for the religious calendar say the moments of the moon's exit from a nakshatra, or the sun's entry into one, are to be calculated with a variable ayanamsha that is 23°15′0″ on 21 March 1956 and then grows by about 50″ a year (item 7), while solar months start a fixed 23°15′ ahead of the vernal equinoctial point (item 5). The civil calendar it proposed is a unified solar calendar based on the tropical year. How many practising astrologers use Lahiri we do not know and will not estimate. If you compare our output against a source using another ayanamsha, expect it to shift every longitude by the difference: on the check case's date, Swiss Ephemeris's SIDM_KRISHNAMURTI is about 6 arcminutes less than Lahiri and SIDM_RAMAN about 1 degree 27 arcminutes less. Against a tropical Western chart, expect roughly 24 degrees at present.

Houses

Whole sign houses. The rising sign becomes the first house in its entirety, the next sign the second, and so on. A planet's house is its sign's distance from the rising sign, and nothing else enters the calculation.

This is our deliberate choice and not a settled historical fact, and this page does not claim that any text requires it. The classical text we consult, Brihat Parashara Hora Shastra, is read in the Ranjan edition, published by Ranjan Publications, New Delhi, translated by R. Santhanam (volume 1) and G.S. Kapoor (volume 2); the translator's preface to volume 1 is dated 1984. We cite no verse for the house rule because we are not saying the text settles it, and we have no survey of practice to cite, so we make no claim about practice. It is certainly not the only basis. Sripati and bhava chalit divide houses by cusp rather than by sign, and a chart cast that way puts some planets in different houses from ours. We do not use Placidus or Koch for interpretation either.

The ascendant degree itself is the same number under every house system, so this choice changes which house a planet falls in, not where the ascendant is.

123456789101112123456789101112AscSMRsame chart,two divisions
Gold, outer ring: houses by sign, the rule this site uses. Cream, inner ring: equal houses, the same twelve houses cut in 30° steps from the ascendant's own degree. The dots are the Sun (S), Moon (M) and Rahu (R) of the fixed case under “Check us”. The Sun and Rahu land in the same house either way; the Moon is in house 12 by sign and house 11 when the houses are cut from the ascendant degree: the Moon is at 6°28′ of Aquarius, and cut from the ascendant degree house 12 does not begin until 13°55′ of Aquarius, so the Moon is still in house 11. Sripati and bhava chalit divide by cusps in ways that differ from an equal cut, so a chart cast that way can differ from both rings.

Lunar nodes

Mean node for Rahu and Ketu, not the true node. Ketu is taken as exactly 180 degrees from Rahu. Both are reported retrograde, which for the mean node is a description rather than a convention: it moves backwards along the ecliptic at a steady rate. The true node is the one that occasionally turns direct, and it is not what we use.

The two differ by up to about 2 degrees: measured against our own engine across 1900 to 2100, the largest gap is 1.98 degrees, on 10 October 1905 (about 21:45 UT; among the daily 00:00 UT samples described under "Reproducing the node figures", the largest is the one on 11 October). On 92.8% of the 73,414 days from 1 January 1900 to 31 December 2100, sampled at 00:00 UT, the two nodes fall in the same nakshatra, and on 96.8% in the same sign. On the other days they do not, and anything read from the node's nakshatra changes with it. It does not change your Vimshottari dasha sequence: that is set by the Moon's nakshatra and nothing else. So if our Rahu disagrees with another chart's by a degree or so, this is why, and the other chart is not necessarily wrong.

true node minus mean node, degrees+2°+1°0−1°−2°Jan 2026Jul 2026Jan 2027Jul 2027
Gold, the mean node, which this site uses, drawn as the flat line at zero because a difference is being plotted. Cream, the true node minus the mean node, every second day for 2026 and 2027. It swings both ways and stays inside about 1.8 degrees over these two years (from −1.76 to +1.77); across 1900 to 2100 the largest gap was 1.98 degrees. Computed with the same engine and data files as the rest of this page; the run is described under “Reproducing those two tables”.

Reproducing the node figures

One date a day at 00:00 UT, from 1 January 1900 to 31 December 2100 (73,414 dates), swe.MEAN_NODE against swe.TRUE_NODE with FLG_SWIEPH | FLG_SIDEREAL, on the pyswisseph version named in the settings table. A node's nakshatra is its sidereal longitude divided by 13°20′, rounded down. The chart of the gap is the 730 days from 1 January 2026, every second day (365 values). The 21:45 UT peak on 10 October 1905 comes from the same nodes scanned at 15-minute steps from 9 to 13 October 1905.

Run that and you should get these numbers. If you do not, we would like to know.

Time and place

The timezone

Birth time is interpreted in the timezone of the place of birth, looked up from the birth coordinates using timezonefinder, which maps a coordinate to an IANA zone from its own boundary polygons.

The lookup has nothing to work with in one case: a chart saved without usable coordinates, or an error in the lookup itself. Then we fall back to the timezone on your account, and if there is none, to Asia/Kolkata. Both fallbacks are guesses, and the first of them is the behaviour this page was corrected for in the correction history. The fallback does not run for coordinates over water. The lookup we call, timezone_at, returns a whole-hour nautical zone there instead of nothing: with the timezonefinder version in the settings table, 0° N 30° W returns Etc/GMT+2. A birth at sea is therefore read in the nautical zone for its longitude, not in the account's timezone. A birth place found through our search is a single point, and we have not tested the lookup for every point on land, so we would rather write down the branches than claim more than we have tested.

Within that zone we apply the historical offset recorded for that date in the IANA timezone database, including any daylight saving of the period.

The timezone database

That database is good but it is not a complete record of civil time. IANA's own theory notes say it is not designed for applications that need accurate handling of all past times everywhere, and Indian history is a good example of why. Asia/Kolkata follows railway time, and the comments in the database itself note that some municipalities kept their former time and that the time in Calcutta depended on whether you were at the railway station or at government offices. Bombay Time, set 4 hours 51 minutes ahead of Greenwich, was maintained until 1955, about nine minutes short of five hours ahead. A clock time written on an Indian certificate from the 1940s may not be the time Asia/Kolkata would reconstruct.

India: Bombay Time to Asia/Kolkata+4:51+5:301955Sri Lanka+6:30+6:00+5:3025 May 199626 Oct 199615 Apr 2006
Two clocks that changed, each on its own timescale rather than one shared axis, since the gap between 1955 and 1996 would otherwise crowd the second row into a sliver. Gold marks the offset each place uses today. Sri Lanka's three dates and both of India's offsets are the ones in the text above and in the correction history; nothing here is a new figure.

So: we apply the recorded history where it exists, and if your birth is early enough for this to matter, tell us and we will set the offset by hand rather than let the database guess.

Coordinates

Coordinates come from a place search against Photon, restricted to features that carry OpenStreetMap's place tag. That tag covers cities, towns and villages and also larger areas such as states and districts, and we do not filter on the type of place. What comes back is the single point Photon gives for the place you choose, which for a state or district is one point representing a large area and can be far from any town. It is not a street address.

The displacement table is measured at the New Delhi case in "Check us". Kilometres become degrees of longitude by km / (111.32 * cos(latitude)), which at 28.6139 N is about 97.72 km per degree; the cosine matters: leaving it out gives about 7.7 arcminutes at 10 km rather than 8.72.

displacementascendant moves
1 km east or west0.87 arcminutes
3 km2.62 arcminutes
5 km4.36 arcminutes
10 km8.72 arcminutes

The last digit depends on which earth model you convert with, so treat these as good to about a hundredth of an arcminute. North to south barely matters: 10 km gives 0.53 arcminutes. Even 10 km east is under a sixth of a degree, so a point a few kilometres from your street will not move your rising sign unless your ascendant was already within a few arcminutes of a boundary. If it was, your birth time matters far more than your street did.

Rounding

None. Longitudes are carried as full double-precision degrees through every stage, and rounding happens only where a number is displayed. Nothing is snapped to a boundary.

Check us

One fixed case, computed by the same function that serves the API.

Enter this1 January 1990, 12:00:00, +05:30, at 28.6139 N, 77.2090 E (New Delhi)
Expect this
QuantityExpected result
Ayanamsha removed (nutation included)23.720706 degrees (23.717417 without nutation)
AscendantPisces 13 degrees 55' 22" (343.922640 decimal degrees)
SunSagittarius 16 degrees 51' 36", Purva Ashadha pada 2 (256.859923 decimal degrees)
MoonAquarius 6 degrees 27' 55", Dhanishtha pada 4 (306.465258 decimal degrees)
Rahu (mean)Capricorn 24 degrees 43' 35", Dhanishtha pada 1 (294.726414 decimal degrees)

Enter that case into any properly configured sidereal engine with Lahiri (nutation included) and the mean node and you should get the same signs, nakshatras and padas, with degrees agreeing to within a few arcseconds. If you get a materially different answer, one of us has a setting wrong, and this page tells you all of ours.

One honest limit on this vector: printed to whole arcseconds it does not by itself prove which ephemeris is loaded, because Moshier and DE441 differ by less than that here. It proves the ayanamsha, the node setting and the house rule. The ephemeris is proved by the flag the library returns, which is how we found we had it wrong.

Run it yourself

Install the pyswisseph version named in the settings table, which this page does not repeat, so there is one place to update it, and put the two data files in a folder called ephe beside this file. These two files, for the ephemeris named in that same settings-table row, have the following SHA-256 digests today; a version or data-file change on that row means these digests are stale and must be regenerated, not assumed to still match:

sepl_18.se1  ca1393ceab3a44fbc895887cf789c68819ae6a1cbc9b22225872dbe4ccd99a66
semo_18.se1  1ca07bd67c24374d77226180c20a4f9996cba013697894810518e7eb582ca4f7

Then run this:

import swisseph as swe

# ephe/ holds the two .se1 files
swe.set_ephe_path("ephe")
swe.set_sid_mode(swe.SIDM_LAHIRI)
flags = swe.FLG_SWIEPH | swe.FLG_SIDEREAL

# 12:00 at +05:30 is 06:30 UT
jd = swe.julday(1990, 1, 1, 6.5)
print(swe.get_ayanamsa_ex_ut(jd, swe.FLG_SWIEPH)[1])
print(swe.get_ayanamsa_ut(jd))
for body in (swe.SUN, swe.MOON, swe.MEAN_NODE):
    print(swe.calc_ut(jd, body, flags)[0][0])
print(swe.houses_ex(jd, 28.6139, 77.2090, b"W", swe.FLG_SIDEREAL)[1][0])

It prints, to six decimals, the ayanamsha the library removes (nutation included, then the value swe.get_ayanamsa_ut gives without nutation), then the sidereal longitudes of the Sun, the Moon and the mean node, then the ascendant: the same six figures already given in decimal degrees, in parentheses, in the Check us table, which is the one place on this page these numbers are written. Pisces begins at 330 degrees, which is why Pisces 13 degrees 55' 22" and its decimal-degree figure in that table agree to the whole arcsecond.

Where else this engine is used

The Choghadiya calculator, also in Hindi, takes its sunrise and sunset from the same Swiss Ephemeris. It does not use the place search or the timezone lookup described in "Time and place": it works from a fixed list of cities, each with its coordinates and its IANA timezone written down, and shows the times in that city's timezone. Choghadiya asks only the weekday and the sunrise and sunset, so the tool uses none of the sidereal settings in the settings table: not the ayanamsha, the house system or the nodes. Sunrise there means the upper limb of the sun with standard refraction, which that page states as one of its own limits.

What this page does not cover

Chart casting, which is everything on this page so far, is not the whole engine. Dasha derivation has its own conventions and is worked through step by step on the nakshatras page instead, including how the birth Moon's position sets the first period and how much of it remains. If you want to reproduce a dasha rather than a chart, start there.

Three things this page does not record: the release of the timezone database the server used, the date of the Photon data behind a place search, and the patch release of Python.

What we do not do

We do not adjust, round or "correct" a stated birth time to produce a tidier chart. If a birth time is uncertain, the honest response is to say which conclusions depend on it, and we say so rather than quietly picking one.

Correction history

Rows that begin with a date were found and fixed on that day. The others were found and fixed on 13 or 14 September 2026, and some of them were later reworded or given a source; the row says what it now claims.

what we saidwhat was truewho it affected
Positions come from the JPL data filesThe files were not installed and the library had silently fallen back to MoshierUnknown for the charts we served, because we have not audited them. In 48,000 sampled positions the two ephemerides put one in a different pada
The data derive from DE431The installed files say DE441 in their own header, and Astrodienst's own page says the Swiss Ephemeris moved to DE441 in May 2026Nobody: a wrong label on the right files
The true node is used for Rahu and KetuThe mean node is used, everywhereAnyone comparing our Rahu against a true-node chart and assuming we agreed
No chart we produced was ever affected by the ephemerisA sampled benchmark cannot support a claim about every chart, and testing it found one pada disagreement in 48,000Stated honestly now: we have not audited the charts we served
Birth time is read in the account's timezoneIt was, and it should have been the birth place's. A London birth was read five and a half hours out, or four and a half during British Summer TimeAnyone for whom the two zones disagreed at their own birth moment. Not everyone born abroad, and not decidable from a country: Sri Lanka matches India today, but the tz database has it at UTC+06:30 from 25 May 1996, UTC+06:00 from 26 October 1996 and back to UTC+05:30 from 15 April 2006, the same three exact days the timeline diagram and this table's own 27 September row give, not the month-level version once written here, so a Colombo birth in that decade moved and one either side of it did not. If a reading from before 13 September 2026 could be affected, ask us and we will run it again
A few kilometres moves the ascendant well under a minute of arcAbout fivefold wrong: 3 km east moves it 2.62 arcminutesNobody: the effect is still small, the number was not
Birth time is read in the timezone of the birth placeIt is, and when the chart has no usable coordinates it falls back to the account timezone and then to Asia/Kolkata. The rule was stated without its fallbackUnknown: the fallback runs only for a chart without usable coordinates, and we have not counted how often that has happened. The undisclosed branch is the defect
SIDM_LAHIRI is the ayanamsha the Calendar Reform Committee adopted for the national calendarThe Committee's civil calendar is a solar calendar based on the tropical year, and the 23°15′00″ reference it fixed for 21 March 1956 is for the religious calendar's nakshatra and solar-month calculations, in its 1955 Report, items 5 and 7 of the religious-calendar recommendations. Swiss Ephemeris's SIDM_LAHIRI (23°15′00.658″) is a later, distinct realization of that referenceA reader checking why our Lahiri differs from another engine's SIDM_LAHIRI_ICRC output, or assuming India's civil calendar is itself sidereal
27 September: the check case's ayanamsha is 23.717417 degreesThat is the value without nutation. The library removes 23.720706 degrees at that date, which is the difference between the tropical and sidereal Sun in the same run; the table and the script now show the value it removesA reader who subtracted 23.717417 from a tropical longitude and compared the result with the table: they were about 12 arcseconds apart
27 September: our place search returns "populated-place centroids"It is restricted to OpenStreetMap's place tag and nothing else, and that tag also covers larger areas such as states, so the point returned can be one point standing for a whole area. The page now says thisAnyone who chose a state or district as a birth place instead of a town; we have not counted how many did
27 September: the summary at the top said birth times are read in the timezone of the birth placeIt left out the fallback to the account's timezone and then to Asia/Kolkata, already corrected in the body; the summary, the figure and its text now state itThe same readers as the earlier timezone row: anyone for whom the fallback ran
27 September: when no zone can be found for the coordinates, the account's timezone and then Asia/Kolkata are usedThat is only for a chart without usable coordinates, or when the lookup itself errors. Coordinates over water, whether open ocean or the English Channel, get an Etc/GMT zone such as Etc/GMT+2 from the lookup, not the fallbackAnyone born at sea, or whose saved coordinates were over water; we have not counted them
27 September: six conversions lie between your birth certificate and your chart, each documented in its own sectionThere are six stages, which is five conversions, and two of them, the step to UTC and the nakshatra and pada step, have no section of their own. The caption now says six stages and that the sections record the settingsNobody: a miscount in a caption
27 September: about once in fifty thousand a sampled position sits close enough to a pada boundary for the ephemerides to disagreeIt was one disagreement in 48,000 sampled positions, and one event is too few to give a rate. The page now states the countNobody: the same paragraph already said the sample says nothing about the charts we served
27 September: Sri Lanka ran UTC+06:30 and then UTC+06:00 from May 1996 until April 2006The tz database has +06:30 from 25 May 1996, +06:00 from 26 October 1996 and +05:30 from 15 April 2006. The sentence put +06:00 in May 1996A reader working out whether a Colombo birth in the summer of 1996 was affected by a timezone error

Last updated 27 September 2026.