🌍 Astrocartography API and ✋ Palmistry API are now live. Ship them in your app today.Get Started
Blog/Use cases

Building astrology compatibility into a dating app

Sun-sign matching can only give 78 answers, and users notice fast. Synastry compares two whole charts, and it takes one API call.

June 5, 2026·10 min read·AstrologyAPI Team
In brief
  • Sun-sign matching gives a whole user base only 78 different answers. Everyone born in one month gets the same verdict about everyone born in another.
  • Synastry compares two whole charts. Moon to Moon shows emotional fit, the Venus and Mars cross-pairs show attraction, aspect angles show quality, and house overlays show life areas.
  • The synastry_horoscope endpoint returns both charts as first and second. Its aspects array describes the composite chart, so you compute the cross-aspects between the two people yourself.
  • Both charts need an exact birth time. So plan a sign-only tier and a disclosed noon default from day one.
  • Never hide matches based on a compatibility score. It shrinks the pool, there is no way to test it against real outcomes, and astrology works better as a conversation starter.

Tinder tested a feature called Astrology Mode. Profiles that showed astrology info got nearly twenty percent more likes from women. Tinder shared that figure at a product keynote on 12 March 2026. The feature is simple. Users add their birth details. The app works out their Sun, Moon, and rising signs. The profile then shows those three signs.

Astrologers were split on it. One critique stood out. Wendy Blume, who edits the Federation of Australian Astrologers journal, wrote in Global Dating Insights in July that the three-sign method leaves out Venus and Mars. In chart reading, those two planets are the ones most tied to love and desire.

Blume's point goes past one feature. Three signs are better than one. But both are still labels on a single person. Synastry is the real step up. Synastry compares two whole birth charts. It says something about the pair, and a badge cannot do that.

A birth chart is a map of the sky at the moment a person was born. Synastry is plain math on two of those maps. Your code can get the result from our API with one call. This piece explains what synastry measures and which endpoints return it. An endpoint is one URL in an API that does one job. The piece also covers users with no birth time. And it argues that a score should never decide who sees whom.

Why Sun-sign matching is not enough

Sun-sign matching can only give 78 different answers across your whole user base. Here is the math. There are twelve signs. Pairing them gives 144 ordered combinations. Many are repeats, like Leo with Scorpio and Scorpio with Leo. Drop the repeats and 78 pairs remain. So everyone born in one month gets the same verdict about everyone born in another month.

Users figure this out fast. Tell a Leo three separate times that she clashes with Scorpios, and she learns what the feature is. It is a fixed lookup table. A fixed table is a weak reason to open an app.

You should still ship this simple tier. The Western suite has an endpoint for it. zodiac_compatibility/:zodiacName/:partnerZodiacName takes two sign names in the URL path. It returns your_sign, your_partner_sign, a compatibility_report string, and a compatibility_percentage. It needs no birth time and no place data. There is nothing to store per user. Show it on a profile card or in a push notification. It also works for users who only gave you a birthday.

Just never use that percentage to rank or match people. The number says almost nothing about the two real people. It was never computed from their data.

What synastry compares

Synastry measures the angles between one person's planets and the other person's planets. Four parts carry most of the meaning. Each part maps to something a product team can reason about.

Moon to Moon

The Moon moves fast. It crosses a zodiac sign in a little over two days. That is why it can tell apart two people born in the same week, while the Sun cannot. In chart reading, the Moon stands for feelings and first reactions. A close Moon-to-Moon contact reads as two people whose quick reactions run at a similar speed. It is the most useful comparison to show. And it sits one subtraction away from data the API already returns.

Venus and Mars

Venus stands for how a person shows love and what draws them in. Mars stands for drive and pursuit. The cross-pairs matter most here. Compare A's Venus with B's Mars, then B's Venus with A's Mars. These are the placements Blume said the three-sign badge leaves out. That gap is why a Sun-sign feature feels thin to users who know some astrology.

Aspect quality

An aspect is the angle between two points on a chart. Only a few angles count. Conjunction sits at 0 degrees, sextile at 60, square at 90, trine at 120, and opposition at 180. Each aspect allows an orb. The orb is the allowed gap on either side of the exact angle. A tighter orb means a stronger contact. Orb sizes vary between astrologers. Six to eight degrees is common for the major aspects, and more for the Sun and Moon. Trines and sextiles read as easy. Squares and oppositions read as tension. A pair with no tension at all usually reads as dull, though. Astrologers do not treat that as the ideal.

House overlays

Houses split a chart into twelve parts, one per life area. They depend on the ascendant, the sign that was rising in the east at birth. The ascendant depends on the birth time down to the minute. An overlay asks which of B's houses A's planets land in. A's Venus in B's seventh house, the partnership house, reads very differently from the same Venus in the sixth. Overlays are the part of synastry that breaks first when the birth time is off. That matters for the fallback section below.

The developer glossary explains house, ascendant, and moon sign. It also names the API field that returns each one.

CHART ACHART BMOON / MOONVENUS / MARS
Cross-aspects are the angles between one chart's planets and the other's. The composite chart is a separate object, covered below.

There is no standard way to turn all this into one number. Astrologers weight the parts differently. Orb rules differ too. And no dataset of relationship outcomes exists to tune the weights against. So any single score your product shows is really a set of choices you made. That is fine to ship. Just know it before the number reaches a ranking function.

The endpoints and what they return

Every two-person endpoint in the Western suite takes the same sixteen fields. The first person's birth data goes in fields that start with p_. The second person's goes in fields that start with s_. That means p_day through p_tzone, and s_day through s_tzone. All calls are POST requests to https://json.astrologyapi.com/v1/. Sign in with HTTP Basic auth. Your user ID is the username. Your API key is the password.

EndpointInputReturns
synastry_horoscopeTwo chartsfirst, second, composite
composite_horoscopeTwo chartsThe same, plus top-level ascendant, midheaven, aspects
love_compatibility_report/tropicalTwo chartslove_report, an array of written paragraphs
romantic_forecast_couple_report/tropicalTwo chartsromantic_forecast, an array of paragraphs
friendship_report/tropicalTwo chartsfriendship_report
romantic_personality_report/tropicalOne chart, plus a house systemreport
zodiac_compatibility/:a/:bTwo sign namescompatibility_report, compatibility_percentage

Build on synastry_horoscope. It returns first and second, one array per person. Each body in those arrays carries name, full_degree, norm_degree, speed, is_retro, sign_id, sign, and house. The response also holds a composite object with its own planets, houses, ascendant, midheaven, and aspects.

Read this before you use aspects

The aspects array sits inside composite. It describes the composite chart, a single midpoint chart blended from both people. Those are not the cross-aspects between the two people. You compute those yourself from the full_degree values in first and second. It takes one subtraction and a small table of angles.

Call the endpointjavascript
// Runs on your server. The API uses HTTP Basic auth and sends no CORS
// headers, so this can never be a browser fetch.
const auth = Buffer.from(
  process.env.ASTRO_USER_ID + ':' + process.env.ASTRO_API_KEY,
).toString('base64')

// Every two-person endpoint wants the same sixteen fields: one set
// prefixed p_, one prefixed s_. Hour and minute are required on both.
const prefixed = (prefix, person) => ({
  [prefix + 'day']: person.day,
  [prefix + 'month']: person.month,
  [prefix + 'year']: person.year,
  [prefix + 'hour']: person.hour,
  [prefix + 'min']: person.min,
  [prefix + 'lat']: person.lat,
  [prefix + 'lon']: person.lon,
  [prefix + 'tzone']: person.tzone,
})

async function synastry(a, b) {
  const res = await fetch(
    'https://json.astrologyapi.com/v1/synastry_horoscope',
    {
      method: 'POST',
      headers: {
        Authorization: 'Basic ' + auth,
        'Content-Type': 'application/json',
      },
      body: JSON.stringify({ ...prefixed('p_', a), ...prefixed('s_', b) }),
    },
  )

  if (!res.ok) {
    throw new Error('synastry_horoscope returned ' + res.status)
  }

  return res.json()
}
Derive the cross-aspectsjavascript
// Orbs here are one common convention, not a standard. Widen them for
// the Sun and Moon if your interpretation copy expects that.
const MAJOR_ASPECTS = [
  { name: 'conjunction', angle: 0, orb: 8 },
  { name: 'sextile', angle: 60, orb: 4 },
  { name: 'square', angle: 90, orb: 6 },
  { name: 'trine', angle: 120, orb: 6 },
  { name: 'opposition', angle: 180, orb: 8 },
]

// Shortest angular distance between two ecliptic longitudes, 0 to 180.
function separation(a, b) {
  const raw = Math.abs(a - b) % 360
  return raw > 180 ? 360 - raw : raw
}

// first and second come straight off the synastry_horoscope response.
function crossAspects(first, second) {
  const found = []

  for (const p of first) {
    for (const s of second) {
      const diff = separation(p.full_degree, s.full_degree)

      for (const aspect of MAJOR_ASPECTS) {
        const orb = Math.abs(diff - aspect.angle)
        if (orb > aspect.orb) continue

        found.push({
          from: p.name,
          to: s.name,
          aspect: aspect.name,
          orb: Number(orb.toFixed(2)),
        })
      }
    }
  }

  // Tighter orb reads as stronger, so sort by it and show the top few.
  return found.sort((x, y) => x.orb - y.orb)
}

const chart = await synastry(personA, personB)
const pairs = crossAspects(chart.first, chart.second)

const moonToMoon = pairs.find((x) => x.from === 'Moon' && x.to === 'Moon')

A trimmed response is below. The field names are the documented ones. The aspect object is copied from the docs word for word. The planet values are shortened to save space.

synastry_horoscope responsejson
{
  "first": [
    {
      "name": "Moon",
      "full_degree": 214.62,
      "norm_degree": 4.62,
      "speed": 12.91,
      "is_retro": "false",
      "sign_id": 8,
      "sign": "Scorpio",
      "house": 5
    }
  ],
  "second": [
    { "name": "Moon", "full_degree": 218.94, "sign": "Scorpio", "house": 11 }
  ],
  "composite": {
    "planets": [],
    "houses": [],
    "ascendant": 0,
    "midheaven": 0,
    "aspects": [
      {
        "aspecting_planet": "Sun",
        "aspected_planet": "Venus",
        "aspecting_planet_id": 0,
        "aspected_planet_id": 5,
        "type": "Semi Sqaure",
        "orb": 4.83,
        "diff": 40.17
      }
    ]
  }
}

Two details in that sample matter. First, look at diff and orb. diff is the measured angle. orb is its distance from the exact aspect angle. A semi-square is exact at 45 degrees. So a diff of 40.17 gives an orb of 4.83. Second, type is a display string, spelling and all. The sample above really does say "Semi Sqaure". So match on the exact values the response sends. Never match on a list of aspect names you typed from memory.

When the birth time is missing

Both charts need an hour and a minute. p_hour, p_min, s_hour, and s_min are all required. So a pair fails when either person left the time blank. In a dating app, that is a large share of pairs. A feature that needs two people to fill in one optional field is a feature most users never see.

Accuracy drops before the call fails. The Moon sits in a sign for about two and a quarter days on average. So a chart built on a guessed time can show the wrong Moon sign. With two people, the risk doubles. If either chart is wrong, the pair result is wrong.

Three patterns work well. The guide on unknown birth times covers all three in depth.

  • Make the sign tier a real feature. Sign-pair compatibility needs two sign names and no birth data at all. Give it its own copy and its own design, so it looks like a separate light feature. It must not look like a broken version of the full one.
  • Default to noon and say so on screen. A stated guess is honest. But hide house overlays when you guess the time. The ascendant moves through a full sign in roughly two hours. Overlays built on a guess are close to noise.
  • Ask for the time later. Don't block signup on it. Ask during profile completion, or when a user first opens a compatibility view. When the time comes in, recompute the charts. Also clear any cached pair results for that user.

One approach always fails. That is guessing midnight in silence and showing the result as if the time were known. It turns a missing field into a confident wrong answer. Users notice that failure, and they do not forgive it.

Start building with real ephemeris data
150 free credits. No card required.

Never let the score decide who sees whom

Never block or hide matches based on a compatibility score. This is our one piece of hard advice here. The rest of this piece describes the API. This section gives an opinion. Display the score. Explain it. Let users sort by it if they insist. But keep it out of the code path that decides whose profile is shown.

We have three reasons. The first is simple math. The pool of people is already the main limit on a dating product. A hard filter removes people from that pool. And it removes them before the user can disagree with the filter.

Second, there is no way to test the score against real outcomes. A normal ranking model learns from results. A synastry score has no results to learn from. And no experiment could produce them fast enough to be useful. Ship an untested score as a hard filter, and you give a guess the force of a rule.

Third, watch what users do with astrology in dating. It works as a shared language. It lets people say something about themselves that would feel awkward said straight. It opens conversations. Tinder's own test figure points the same way. The lift came from profiles that showed astrology info. Nothing was filtered to get that lift.

A compatibility score is a good reason to send a message. It is a bad reason to hide a person.

The report endpoints fit the opener job. Send a pair to love_compatibility_report/tropical and love_report comes back as an array of written paragraphs. romantic_forecast_couple_report/tropical returns romantic_forecast the same way. friendship_report/tropical covers products with a non-romantic mode. Those paragraphs give two people something to talk about. Drop one line into the chat box as a suggested first message. That does a job no percentage can do.

Here is the honest limit. We have no retention data that proves the opener approach beats the filter approach. And if we had such data, you should still doubt it, because we sell the API. What we can say plainly is how the two failures differ. If the opener fails, someone gets a dull first line. If the filter fails, someone never sees a person they would have liked.

Birth data is sensitive personal data

Date, time, and place of birth together come close to a unique ID for a person. Some laws treat what can be read from it as sensitive. And the data never expires. A user can change a leaked password. Nobody can change their moment of birth.

Four rules cost nothing to follow. First, say why you collect the data on the same screen where you ask for it. A policy page is too far away. Second, store the resolved UTC time and the map coordinates. A free-text place name has to be turned into coordinates again later, and you will not always get the same answer. Third, keep birth fields out of URLs, analytics events, and log lines. All three reach outside companies by default. Fourth, when a user deletes their account, delete the birth record and every cached pair result computed from it.

One more rule is specific to this feature. Compute the pair on your server and return only the result. Never send one user the other user's chart. A synastry response holds full planet positions for both people. The full_degree values alone are enough to work out someone's birth moment fairly closely. Pass the raw response to a client, and you have handed one user another user's birth data.

What it costs to run

Entry to the Western suite is $49 per month, ₹2,999 in India. New accounts get 150 free credits. That is enough to build and test the whole feature before you pay anything.

The per-call rate matters less than your call pattern. A pair's synastry never changes. Both birth moments are fixed, so the comparison between them is fixed too. Compute it once per pair and store the derived aspects. One call then covers the whole life of a conversation.

The costly pattern is scoring at search time. That means running synastry against every profile in a stack the user will mostly swipe past. Score on profile view or on match instead. There is also a cheap ranking signal for a whole pool. Each user's Moon and Venus positions come from their own chart, computed once at signup. The gap between any two users is then plain arithmetic. Your database can do it without another API call. The pay-as-you-go guide explains how credits work. The pricing page lists the volume rates.

What to build

Indian matrimony products solved a nearby problem years ago, in their own way. Ashtakoot scoring is a settled system with published points. Users there expect a number, so the question is how to present it well. We wrote about that in kundli matching for matrimony platforms. Western dating users have no such settled system. That is a limit, but it is also a freedom. No rule forces you to show a score.

Use that freedom. Skip the single big score. Compute the pair honestly. Show the two or three contacts that say something real about these two people. Write the copy as an observation, and let it start a conversation. The choice of who to message stays with the user.

Frequently asked questions

How does astrology matching work in a dating app?

The app computes two birth charts from date, time, and place of birth. Then it compares them. That comparison is called synastry. It measures the angles between one person’s planets and the other person’s planets. Moon to Moon, Venus to Mars, and house overlays carry most of the meaning.

Do you need a birth time for astrology compatibility?

For synastry, yes, on both sides. Hour and minute are required fields. House overlays depend on the ascendant, and the ascendant changes sign about every two hours. Sign-name compatibility needs no birth time at all, so it is the right fallback tier.

Western or Vedic for a global dating audience?

Use Western tropical synastry for a general global audience. Those users already read horoscopes in that system. Use Vedic Ashtakoot scoring where users expect it, mainly Indian and diaspora matrimony products. There, a 36-point score is the settled norm.

What does a compatibility API return?

Two kinds of output. Structured endpoints return planet positions in degrees for both people, plus the composite chart. You read the meaning out of those yourself. Report endpoints return arrays of written paragraphs you can show directly. Sign-pair endpoints return a short report plus a percentage.

Sources
  1. 01Tinder Debuts Inaugural Product Keynote Tinder Sparks 2026 (Tinder press room, 12 March 2026)
  2. 02Tinder’s Astrology Mode Sees Success, But Skepticism (Global Dating Insights, 2 July 2026)
Further reading
Start building with real ephemeris data
150 free credits. No card required.
Related