β Like this project? Star it on GitHub and help it grow! β
ΒKerykeion is a Python library for astrology. It computes planetary and house positions, detects aspects, and generates SVG charts β including birth, synastry, transit, and composite charts. You can also customize which planets to include in your calculations.
The main goal of this project is to offer a clean, data-driven approach to astrology, making it accessible and programmable.
Kerykeion also integrates seamlessly with LLM and AI applications.
Here is an example of a birthchart:
If you want to use Kerykeion in a web application or for commercial or closed-source purposes, you can try the dedicated web API:
It is open source and directly supports this project.
- Commercial Web API
- Table of Contents
- Installation
- Quick Start
- Basic Usage
- Generate a SVG Chart
- Wheel Only Charts
- Report Generator
- AI Context Serializer
- Example: Retrieving Aspects
- Relationship Score
- Element & Quality Distribution Strategies
- Ayanamsa (Sidereal Modes)
- House Systems
- Perspective Type
- Themes
- Alternative Initialization
- Lunar Nodes (Rahu & Ketu)
- JSON Support
- Documentation
- Projects built with Kerykeion
- Development
- Integrating Kerykeion into Your Project
- License
- Contributing
- Citations
Kerykeion requires Python 3.9 or higher.
pip3 install kerykeionFor more installation options and environment setup, see the Getting Started guide.
from pathlib import Path
from kerykeion import AstrologicalSubjectFactory
from kerykeion.chart_data_factory import ChartDataFactory
from kerykeion.charts.chart_drawer import ChartDrawer
subject = AstrologicalSubjectFactory.from_birth_data(
name="Example Person",
year=1990, month=7, day=15,
hour=10, minute=30,
lng=12.4964,
lat=41.9028,
tz_str="Europe/Rome",
online=False,
)
chart_data = ChartDataFactory.create_natal_chart_data(subject)
chart_drawer = ChartDrawer(chart_data=chart_data)
output_dir = Path("charts_output")
output_dir.mkdir(exist_ok=True)
chart_drawer.save_svg(output_path=output_dir, filename="example-natal")
print("Chart saved to", (output_dir / "example-natal.svg").resolve())This script shows the recommended workflow:
- Create an
AstrologicalSubjectwith explicit coordinates and timezone (offline mode). - Build a
ChartDataModelthroughChartDataFactory. - Render the SVG via
ChartDrawer, saving it to a controlled folder (charts_output).
Use the same pattern for synastry, composite, transit, or return charts by swapping the factory method.
π More examples: kerykeion.net/examples
Below is a simple example illustrating the creation of an astrological subject and retrieving astrological details:
from kerykeion import AstrologicalSubjectFactory
# Create an instance of the AstrologicalSubjectFactory class.
# Arguments: Name, year, month, day, hour, minutes, city, nation
john = AstrologicalSubjectFactory.from_birth_data(
"John Lennon", 1940, 10, 9, 18, 30,
lng=-2.9833,
lat=53.4,
tz_str="Europe/London",
online=False,
)
# Retrieve information about the Sun:
print(john.sun.model_dump_json())
# > {"name":"Sun","quality":"Cardinal","element":"Air","sign":"Lib","sign_num":6,"position":16.26789199474399,"abs_pos":196.267891994744,"emoji":"βοΈ","point_type":"AstrologicalPoint","house":"Sixth_House","retrograde":false}
# Retrieve information about the first house:
print(john.first_house.model_dump_json())
# > {"name":"First_House","quality":"Cardinal","element":"Fire","sign":"Ari","sign_num":0,"position":19.74676624176799,"abs_pos":19.74676624176799,"emoji":"βοΈ","point_type":"House","house":null,"retrograde":null}
# Retrieve the element of the Moon sign:
print(john.moon.element)
# > 'Air'Working offline: pass
online=Falseand specifylng,lat, andtz_stras shown above.
Working online: setonline=Trueand providecity,nation, and a valid GeoNames username. Register for free at geonames.org. You can set the username via theKERYKEION_GEONAMES_USERNAMEenvironment variable or thegeonames_usernameparameter.
π Full factory documentation: AstrologicalSubjectFactory
To avoid GeoNames, provide longitude, latitude, and timezone and set online=False:
john = AstrologicalSubjectFactory.from_birth_data(
"John Lennon", 1940, 10, 9, 18, 30,
city="Liverpool",
nation="GB",
lng=-2.9833, # Longitude for Liverpool
lat=53.4000, # Latitude for Liverpool
tz_str="Europe/London", # Timezone for Liverpool
online=False,
)All chart-rendering examples below create a local charts_output/ folder so the tests can write without touching your home directory. Feel free to change the path when integrating into your own projects.
To generate a chart, use the ChartDataFactory to pre-compute chart data, then ChartDrawer to create the visualization. This two-step process ensures clean separation between astrological calculations and chart rendering.
π Chart generation docs: Charts Documentation
Tip:
The optimized way to open the generated SVG files is with a web browser (e.g., Chrome, Firefox).
To improve compatibility across different applications, you can use the remove_css_variables parameter when generating the SVG. This will inline all styles and eliminate CSS variables, resulting in an SVG that is more broadly supported.
from pathlib import Path
from kerykeion import AstrologicalSubjectFactory
from kerykeion.chart_data_factory import ChartDataFactory
from kerykeion.charts.chart_drawer import ChartDrawer
# Step 1: Create subject
john = AstrologicalSubjectFactory.from_birth_data(
"John Lennon", 1940, 10, 9, 18, 30,
lng=-2.9833,
lat=53.4,
tz_str="Europe/London",
online=False,
)
# Step 2: Pre-compute chart data
chart_data = ChartDataFactory.create_natal_chart_data(john)
# Step 3: Create visualization
birth_chart_svg = ChartDrawer(chart_data=chart_data)
output_dir = Path("charts_output")
output_dir.mkdir(exist_ok=True)
birth_chart_svg.save_svg(output_path=output_dir, filename="john-lennon-natal")The SVG file is saved under charts_output/john-lennon-natal.svg.
π More birth chart examples: Birth Chart Guide
An "external" birth chart places the zodiac wheel on the outer ring, offering an alternative visualization style:
from pathlib import Path
from kerykeion import AstrologicalSubjectFactory
from kerykeion.chart_data_factory import ChartDataFactory
from kerykeion.charts.chart_drawer import ChartDrawer
# Step 1: Create subject
birth_chart = AstrologicalSubjectFactory.from_birth_data(
"John Lennon", 1940, 10, 9, 18, 30,
lng=-2.9833,
lat=53.4,
tz_str="Europe/London",
online=False,
)
# Step 2: Pre-compute chart data for external natal chart
chart_data = ChartDataFactory.create_natal_chart_data(birth_chart)
# Step 3: Create visualization with external_view=True
birth_chart_svg = ChartDrawer(chart_data=chart_data, external_view=True)
output_dir = Path("charts_output")
output_dir.mkdir(exist_ok=True)
birth_chart_svg.save_svg(output_path=output_dir, filename="john-lennon-natal-external")Synastry charts overlay two individuals' planetary positions to analyze relationship compatibility:
from pathlib import Path
from kerykeion import AstrologicalSubjectFactory
from kerykeion.chart_data_factory import ChartDataFactory
from kerykeion.charts.chart_drawer import ChartDrawer
# Step 1: Create subjects
first = AstrologicalSubjectFactory.from_birth_data(
"John Lennon", 1940, 10, 9, 18, 30,
lng=-2.9833,
lat=53.4,
tz_str="Europe/London",
online=False,
)
second = AstrologicalSubjectFactory.from_birth_data(
"Paul McCartney", 1942, 6, 18, 15, 30,
lng=-2.9833,
lat=53.4,
tz_str="Europe/London",
online=False,
)
# Step 2: Pre-compute synastry chart data
chart_data = ChartDataFactory.create_synastry_chart_data(first, second)
# Step 3: Create visualization
synastry_chart = ChartDrawer(chart_data=chart_data)
output_dir = Path("charts_output")
output_dir.mkdir(exist_ok=True)
synastry_chart.save_svg(output_path=output_dir, filename="lennon-mccartney-synastry")π Synastry chart guide: Synastry Chart Examples
Transit charts compare current planetary positions against a natal chart:
from pathlib import Path
from kerykeion import AstrologicalSubjectFactory
from kerykeion.chart_data_factory import ChartDataFactory
from kerykeion.charts.chart_drawer import ChartDrawer
# Step 1: Create subjects
transit = AstrologicalSubjectFactory.from_birth_data(
"Transit", 2025, 6, 8, 8, 45,
lng=-84.3880,
lat=33.7490,
tz_str="America/New_York",
online=False,
)
subject = AstrologicalSubjectFactory.from_birth_data(
"John Lennon", 1940, 10, 9, 18, 30,
lng=-2.9833,
lat=53.4,
tz_str="Europe/London",
online=False,
)
# Step 2: Pre-compute transit chart data
chart_data = ChartDataFactory.create_transit_chart_data(subject, transit)
# Step 3: Create visualization
transit_chart = ChartDrawer(chart_data=chart_data)
output_dir = Path("charts_output")
output_dir.mkdir(exist_ok=True)
transit_chart.save_svg(output_path=output_dir, filename="john-lennon-transit")π Transit chart guide: Transit Chart Examples
Solar returns calculate the exact moment the Sun returns to its natal position each year:
from pathlib import Path
from kerykeion import AstrologicalSubjectFactory
from kerykeion.planetary_return_factory import PlanetaryReturnFactory
from kerykeion.chart_data_factory import ChartDataFactory
from kerykeion.charts.chart_drawer import ChartDrawer
# Step 1: Create natal subject
john = AstrologicalSubjectFactory.from_birth_data(
"John Lennon", 1940, 10, 9, 18, 30,
lng=-2.9833,
lat=53.4,
tz_str="Europe/London",
online=False,
)
# Step 2: Calculate Solar Return subject (offline example with manual coordinates)
return_factory = PlanetaryReturnFactory(
john,
lng=-2.9833,
lat=53.4000,
tz_str="Europe/London",
online=False
)
solar_return_subject = return_factory.next_return_from_date(1964, 10, 1, return_type="Solar")
# Step 3: Pre-compute return chart data (dual wheel: natal + solar return)
chart_data = ChartDataFactory.create_return_chart_data(john, solar_return_subject)
# Step 4: Create visualization
solar_return_chart = ChartDrawer(chart_data=chart_data)
output_dir = Path("charts_output")
output_dir.mkdir(exist_ok=True)
solar_return_chart.save_svg(output_path=output_dir, filename="john-lennon-solar-return-dual")π Return chart guide: Dual Return Chart Examples
from pathlib import Path
from kerykeion import AstrologicalSubjectFactory
from kerykeion.planetary_return_factory import PlanetaryReturnFactory
from kerykeion.chart_data_factory import ChartDataFactory
from kerykeion.charts.chart_drawer import ChartDrawer
# Step 1: Create natal subject
john = AstrologicalSubjectFactory.from_birth_data(
"John Lennon", 1940, 10, 9, 18, 30,
lng=-2.9833,
lat=53.4,
tz_str="Europe/London",
online=False,
)
# Step 2: Calculate Solar Return subject (offline example with manual coordinates)
return_factory = PlanetaryReturnFactory(
john,
lng=-2.9833,
lat=53.4000,
tz_str="Europe/London",
online=False
)
solar_return_subject = return_factory.next_return_from_date(1964, 10, 1, return_type="Solar")
# Step 3: Build a single-wheel return chart
chart_data = ChartDataFactory.create_single_wheel_return_chart_data(solar_return_subject)
# Step 4: Create visualization
single_wheel_chart = ChartDrawer(chart_data=chart_data)
output_dir = Path("charts_output")
output_dir.mkdir(exist_ok=True)
single_wheel_chart.save_svg(output_path=output_dir, filename="john-lennon-solar-return-single")π Planetary return factory docs: PlanetaryReturnFactory
Lunar returns calculate when the Moon returns to its natal position (approximately monthly):
from pathlib import Path
from kerykeion import AstrologicalSubjectFactory
from kerykeion.planetary_return_factory import PlanetaryReturnFactory
from kerykeion.chart_data_factory import ChartDataFactory
from kerykeion.charts.chart_drawer import ChartDrawer
# Step 1: Create natal subject
john = AstrologicalSubjectFactory.from_birth_data(
"John Lennon", 1940, 10, 9, 18, 30,
lng=-2.9833,
lat=53.4,
tz_str="Europe/London",
online=False,
)
# Step 2: Calculate Lunar Return subject
return_factory = PlanetaryReturnFactory(
john,
lng=-2.9833,
lat=53.4000,
tz_str="Europe/London",
online=False
)
lunar_return_subject = return_factory.next_return_from_date(1964, 1, 1, return_type="Lunar")
# Step 3: Build a dual wheel (natal + lunar return)
lunar_return_chart_data = ChartDataFactory.create_return_chart_data(john, lunar_return_subject)
dual_wheel_chart = ChartDrawer(chart_data=lunar_return_chart_data)
output_dir = Path("charts_output")
output_dir.mkdir(exist_ok=True)
dual_wheel_chart.save_svg(output_path=output_dir, filename="john-lennon-lunar-return-dual")
# Optional: create a single-wheel lunar return
single_wheel_data = ChartDataFactory.create_single_wheel_return_chart_data(lunar_return_subject)
single_wheel_chart = ChartDrawer(chart_data=single_wheel_data)
single_wheel_chart.save_svg(output_path=output_dir, filename="john-lennon-lunar-return-single")Composite charts create a single chart from two individuals' midpoints to represent the relationship entity:
from pathlib import Path
from kerykeion import CompositeSubjectFactory, AstrologicalSubjectFactory
from kerykeion.chart_data_factory import ChartDataFactory
from kerykeion.charts.chart_drawer import ChartDrawer
# Step 1: Create subjects (offline configuration)
angelina = AstrologicalSubjectFactory.from_birth_data(
"Angelina Jolie", 1975, 6, 4, 9, 9,
lng=-118.2437,
lat=34.0522,
tz_str="America/Los_Angeles",
online=False,
)
brad = AstrologicalSubjectFactory.from_birth_data(
"Brad Pitt", 1963, 12, 18, 6, 31,
lng=-96.7069,
lat=35.3273,
tz_str="America/Chicago",
online=False,
)
# Step 2: Create composite subject
factory = CompositeSubjectFactory(angelina, brad)
composite_model = factory.get_midpoint_composite_subject_model()
# Step 3: Pre-compute composite chart data
chart_data = ChartDataFactory.create_composite_chart_data(composite_model)
# Step 4: Create visualization
composite_chart = ChartDrawer(chart_data=chart_data)
output_dir = Path("charts_output")
output_dir.mkdir(exist_ok=True)
composite_chart.save_svg(output_path=output_dir, filename="jolie-pitt-composite")π Composite factory docs: CompositeSubjectFactory
For all the charts, you can generate a wheel-only chart by using the method save_wheel_only_svg_file():
π Minimalist charts guide: Wheel Only & Aspect Grid Charts
from pathlib import Path
from kerykeion import AstrologicalSubjectFactory
from kerykeion.chart_data_factory import ChartDataFactory
from kerykeion.charts.chart_drawer import ChartDrawer
# Step 1: Create subject
birth_chart = AstrologicalSubjectFactory.from_birth_data(
"John Lennon", 1940, 10, 9, 18, 30,
lng=-2.9833,
lat=53.4,
tz_str="Europe/London",
online=False,
)
# Step 2: Pre-compute chart data
chart_data = ChartDataFactory.create_natal_chart_data(birth_chart)
# Step 3: Create visualization
birth_chart_svg = ChartDrawer(chart_data=chart_data)
output_dir = Path("charts_output")
output_dir.mkdir(exist_ok=True)
birth_chart_svg.save_wheel_only_svg_file(output_path=output_dir, filename="john-lennon-natal-wheel")from pathlib import Path
from kerykeion import AstrologicalSubjectFactory
from kerykeion.chart_data_factory import ChartDataFactory
from kerykeion.charts.chart_drawer import ChartDrawer
# Step 1: Create subject
birth_chart = AstrologicalSubjectFactory.from_birth_data(
"John Lennon", 1940, 10, 9, 18, 30,
lng=-2.9833,
lat=53.4,
tz_str="Europe/London",
online=False,
)
# Step 2: Pre-compute external natal chart data
chart_data = ChartDataFactory.create_natal_chart_data(birth_chart)
# Step 3: Create visualization (external wheel view)
birth_chart_svg = ChartDrawer(chart_data=chart_data, external_view=True)
output_dir = Path("charts_output")
output_dir.mkdir(exist_ok=True)
birth_chart_svg.save_wheel_only_svg_file(output_path=output_dir, filename="john-lennon-natal-wheel-external")from pathlib import Path
from kerykeion import AstrologicalSubjectFactory
from kerykeion.chart_data_factory import ChartDataFactory
from kerykeion.charts.chart_drawer import ChartDrawer
# Step 1: Create subjects
first = AstrologicalSubjectFactory.from_birth_data(
"John Lennon", 1940, 10, 9, 18, 30,
lng=-2.9833,
lat=53.4,
tz_str="Europe/London",
online=False,
)
second = AstrologicalSubjectFactory.from_birth_data(
"Paul McCartney", 1942, 6, 18, 15, 30,
lng=-2.9833,
lat=53.4,
tz_str="Europe/London",
online=False,
)
# Step 2: Pre-compute synastry chart data
chart_data = ChartDataFactory.create_synastry_chart_data(first, second)
# Step 3: Create visualization
synastry_chart = ChartDrawer(chart_data=chart_data)
output_dir = Path("charts_output")
output_dir.mkdir(exist_ok=True)
synastry_chart.save_wheel_only_svg_file(output_path=output_dir, filename="lennon-mccartney-synastry-wheel")To save the SVG file in a custom location, specify the output_path parameter in save_svg():
from pathlib import Path
from kerykeion import AstrologicalSubjectFactory
from kerykeion.chart_data_factory import ChartDataFactory
from kerykeion.charts.chart_drawer import ChartDrawer
# Step 1: Create subjects
first = AstrologicalSubjectFactory.from_birth_data(
"John Lennon", 1940, 10, 9, 18, 30,
lng=-2.9833,
lat=53.4,
tz_str="Europe/London",
online=False,
)
second = AstrologicalSubjectFactory.from_birth_data(
"Paul McCartney", 1942, 6, 18, 15, 30,
lng=-2.9833,
lat=53.4,
tz_str="Europe/London",
online=False,
)
# Step 2: Pre-compute synastry chart data
chart_data = ChartDataFactory.create_synastry_chart_data(first, second)
# Step 3: Create visualization with custom output directory
synastry_chart = ChartDrawer(chart_data=chart_data)
output_dir = Path("charts_output")
output_dir.mkdir(exist_ok=True)
synastry_chart.save_svg(output_path=output_dir)
print("Saved to", (output_dir / f"{synastry_chart.first_obj.name} - Synastry Chart.svg").resolve())You can switch chart language by passing chart_language to the ChartDrawer class:
from pathlib import Path
from kerykeion import AstrologicalSubjectFactory
from kerykeion.chart_data_factory import ChartDataFactory
from kerykeion.charts.chart_drawer import ChartDrawer
# Step 1: Create subject
birth_chart = AstrologicalSubjectFactory.from_birth_data(
"John Lennon", 1940, 10, 9, 18, 30,
lng=-2.9833,
lat=53.4,
tz_str="Europe/London",
online=False,
)
# Step 2: Pre-compute chart data
chart_data = ChartDataFactory.create_natal_chart_data(birth_chart)
# Step 3: Create visualization with Italian language
birth_chart_svg = ChartDrawer(
chart_data=chart_data,
chart_language="IT" # Change to Italian
)
output_dir = Path("charts_output")
output_dir.mkdir(exist_ok=True)
birth_chart_svg.save_svg(output_path=output_dir, filename="john-lennon-natal-it")You can also provide custom labels (or introduce a brand-new language) by passing
a dictionary to language_pack. Only the keys you supply are merged on top of the
built-in strings:
from pathlib import Path
from kerykeion import AstrologicalSubjectFactory
from kerykeion.chart_data_factory import ChartDataFactory
from kerykeion.charts.chart_drawer import ChartDrawer
birth_chart = AstrologicalSubjectFactory.from_birth_data(
"John Lennon", 1940, 10, 9, 18, 30,
lng=-2.9833,
lat=53.4,
tz_str="Europe/London",
online=False,
)
chart_data = ChartDataFactory.create_natal_chart_data(birth_chart)
custom_labels = {
"PT": {
"info": "InformaΓ§Γ΅es",
"celestial_points": {"Sun": "Sol", "Moon": "Lua"},
}
}
custom_chart = ChartDrawer(
chart_data=chart_data,
chart_language="PT",
language_pack=custom_labels["PT"],
)
output_dir = Path("charts_output")
output_dir.mkdir(exist_ok=True)
custom_chart.save_svg(output_path=output_dir, filename="john-lennon-natal-pt")π Language configuration guide: Chart Language Settings
The available languages are:
- EN (English)
- FR (French)
- PT (Portuguese)
- ES (Spanish)
- TR (Turkish)
- RU (Russian)
- IT (Italian)
- CN (Chinese)
- DE (German)
To generate a minified SVG, set minify=True in the save_svg() method:
from pathlib import Path
from kerykeion import AstrologicalSubjectFactory
from kerykeion.chart_data_factory import ChartDataFactory
from kerykeion.charts.chart_drawer import ChartDrawer
# Step 1: Create subject
birth_chart = AstrologicalSubjectFactory.from_birth_data(
"John Lennon", 1940, 10, 9, 18, 30,
lng=-2.9833,
lat=53.4,
tz_str="Europe/London",
online=False,
)
# Step 2: Pre-compute chart data
chart_data = ChartDataFactory.create_natal_chart_data(birth_chart)
# Step 3: Create visualization
birth_chart_svg = ChartDrawer(chart_data=chart_data)
output_dir = Path("charts_output")
output_dir.mkdir(exist_ok=True)
birth_chart_svg.save_svg(
output_path=output_dir,
filename="john-lennon-natal-minified",
minify=True,
)To generate an SVG without CSS variables, set remove_css_variables=True in the save_svg() method:
from pathlib import Path
from kerykeion import AstrologicalSubjectFactory
from kerykeion.chart_data_factory import ChartDataFactory
from kerykeion.charts.chart_drawer import ChartDrawer
# Step 1: Create subject
birth_chart = AstrologicalSubjectFactory.from_birth_data(
"John Lennon", 1940, 10, 9, 18, 30,
lng=-2.9833,
lat=53.4,
tz_str="Europe/London",
online=False,
)
# Step 2: Pre-compute chart data
chart_data = ChartDataFactory.create_natal_chart_data(birth_chart)
# Step 3: Create visualization
birth_chart_svg = ChartDrawer(chart_data=chart_data)
output_dir = Path("charts_output")
output_dir.mkdir(exist_ok=True)
birth_chart_svg.save_svg(
output_path=output_dir,
filename="john-lennon-natal-no-css-variables",
remove_css_variables=True,
)This will inline all styles and eliminate CSS variables, resulting in an SVG that is more broadly supported.
It's possible to generate a grid-only SVG, useful for creating a custom layout. To do this, use the save_aspect_grid_only_svg_file() method:
from pathlib import Path
from kerykeion import AstrologicalSubjectFactory
from kerykeion.chart_data_factory import ChartDataFactory
from kerykeion.charts.chart_drawer import ChartDrawer
# Step 1: Create subjects
birth_chart = AstrologicalSubjectFactory.from_birth_data(
"John Lennon", 1940, 10, 9, 18, 30,
lng=-2.9833,
lat=53.4,
tz_str="Europe/London",
online=False,
)
second = AstrologicalSubjectFactory.from_birth_data(
"Paul McCartney", 1942, 6, 18, 15, 30,
lng=-2.9833,
lat=53.4,
tz_str="Europe/London",
online=False,
)
# Step 2: Pre-compute synastry chart data
chart_data = ChartDataFactory.create_synastry_chart_data(birth_chart, second)
# Step 3: Create visualization with dark theme
aspect_grid_chart = ChartDrawer(chart_data=chart_data, theme="dark")
output_dir = Path("charts_output")
output_dir.mkdir(exist_ok=True)
aspect_grid_chart.save_aspect_grid_only_svg_file(output_path=output_dir, filename="lennon-mccartney-aspect-grid")ReportGenerator mirrors the chart-type dispatch of ChartDrawer. It accepts raw AstrologicalSubjectModel instances as well as any ChartDataModel produced by ChartDataFactoryβincluding natal, composite, synastry, transit, and planetary return chartsβand renders the appropriate textual report automatically.
π Full report documentation: Report Generator Guide
from kerykeion import ReportGenerator, AstrologicalSubjectFactory, ChartDataFactory
# Subject-only report
subject = AstrologicalSubjectFactory.from_birth_data(
"Sample Natal", 1990, 7, 21, 14, 45,
lng=12.4964,
lat=41.9028,
tz_str="Europe/Rome",
online=False,
)
ReportGenerator(subject).print_report(include_aspects=False)
# Single-chart data (elements, qualities, aspects enabled)
natal_data = ChartDataFactory.create_natal_chart_data(subject)
ReportGenerator(natal_data).print_report(max_aspects=10)
# Dual-chart data (synastry, transit, dual return, β¦)
partner = AstrologicalSubjectFactory.from_birth_data(
"Sample Partner", 1992, 11, 5, 9, 30,
lng=12.4964,
lat=41.9028,
tz_str="Europe/Rome",
online=False,
)
synastry_data = ChartDataFactory.create_synastry_chart_data(subject, partner)
ReportGenerator(synastry_data).print_report(max_aspects=12)Each report contains:
- A chart-aware title summarising the subject(s) and chart type
- Birth/event metadata and configuration settings
- Celestial points with sign, position, daily motion, declination, retrograde flag, and house
- House cusp tables for every subject involved
- Lunar phase details when available
- Element/quality distributions and active configuration summaries (for chart data)
- Aspect listings tailored for single or dual charts, with symbols for type and movement
- Dual-chart extras such as house comparisons and relationship scores (when provided by the data)
All section helpers remain available for targeted output:
from kerykeion import ReportGenerator, AstrologicalSubjectFactory, ChartDataFactory
subject = AstrologicalSubjectFactory.from_birth_data(
"Sample Natal", 1990, 7, 21, 14, 45,
lng=12.4964,
lat=41.9028,
tz_str="Europe/Rome",
online=False,
)
natal_data = ChartDataFactory.create_natal_chart_data(subject)
report = ReportGenerator(natal_data)
sections = report.generate_report(max_aspects=5).split("\n\n")
for section in sections[:3]:
print(section)π Report examples: Report Examples
The context_serializer module transforms Kerykeion data models into precise, non-qualitative text optimized for LLM consumption. It provides the essential "ground truth" data needed for AI agents to generate accurate astrological interpretations.
π Full context serializer docs: Context Serializer Guide
from kerykeion import AstrologicalSubjectFactory, to_context
# Create a subject
subject = AstrologicalSubjectFactory.from_birth_data(
"John Doe", 1990, 1, 1, 12, 0,
city="London",
nation="GB",
lng=-0.1278,
lat=51.5074,
tz_str="Europe/London",
online=False,
)
# Generate AI-ready context
context = to_context(subject)
print(context)Output:
Chart for John Doe
Birth data: 1990-01-01 12:00, London, GB
...
Celestial Points:
- Sun at 10.81Β° in Capricorn in Tenth House, quality: Cardinal, element: Earth...
- Moon at 25.60Β° in Aquarius in Eleventh House, quality: Fixed, element: Air...
Key Features:
- Standardized Output: Consistent format for Natal, Synastry, Composite, and Return charts.
- Non-Qualitative: Provides raw data (positions, aspects) without interpretive bias.
- Prompt-Ready: Designed to be injected directly into system prompts.
Kerykeion provides a unified AspectsFactory class for calculating astrological aspects within single charts or between two charts:
from kerykeion import AspectsFactory, AstrologicalSubjectFactory
# Create astrological subjects
jack = AstrologicalSubjectFactory.from_birth_data(
"Jack", 1990, 6, 15, 15, 15,
lng=12.4964,
lat=41.9028,
tz_str="Europe/Rome",
online=False,
)
jane = AstrologicalSubjectFactory.from_birth_data(
"Jane", 1991, 10, 25, 21, 0,
lng=12.4964,
lat=41.9028,
tz_str="Europe/Rome",
online=False,
)
# For single chart aspects (natal, return, composite, etc.)
single_chart_result = AspectsFactory.single_chart_aspects(jack)
print(f"Found {len(single_chart_result.aspects)} aspects in Jack's chart")
print(single_chart_result.aspects[0])
# For dual chart aspects (synastry, transits, comparisons, etc.)
dual_chart_result = AspectsFactory.dual_chart_aspects(jack, jane)
print(f"Found {len(dual_chart_result.aspects)} aspects between Jack and Jane's charts")
print(dual_chart_result.aspects[0])
# Each AspectModel includes:
# - p1_name, p2_name: Planet/point names
# - aspect: Aspect type (conjunction, trine, square, etc.)
# - orbit: Orb tolerance in degrees
# - aspect_degrees: Exact degrees for the aspect (0, 60, 90, 120, 180, etc.)
# - color: Hex color code for visualizationπ Aspects documentation: Aspects Factory Guide
Advanced Usage with Custom Settings:
# You can also customize aspect calculations with custom orb settings
from kerykeion.settings.config_constants import DEFAULT_ACTIVE_ASPECTS
# Modify aspect settings if needed
custom_aspects = DEFAULT_ACTIVE_ASPECTS.copy()
# ... modify as needed
# The factory automatically uses the configured settings for orb calculations
# and filters aspects based on relevance and orb thresholdsπ Configuration options: Settings Documentation
Kerykeion can calculate a relationship compatibility score based on synastry aspects, using the method of the Italian astrologer Ciro Discepolo:
from kerykeion import AstrologicalSubjectFactory
from kerykeion.relationship_score_factory import RelationshipScoreFactory
# Create two subjects
person1 = AstrologicalSubjectFactory.from_birth_data(
"Alice", 1990, 3, 15, 14, 30,
lng=12.4964,
lat=41.9028,
tz_str="Europe/Rome",
online=False,
)
person2 = AstrologicalSubjectFactory.from_birth_data(
"Bob", 1988, 7, 22, 9, 0,
lng=12.4964,
lat=41.9028,
tz_str="Europe/Rome",
online=False,
)
# Calculate relationship score
score_factory = RelationshipScoreFactory(person1, person2)
result = score_factory.get_score()
print(f"Compatibility Score: {result.score}")
print(f"Description: {result.description}")π Relationship score guide: Relationship Score Examples
π Factory documentation: RelationshipScoreFactory
ChartDataFactory now offers two strategies for calculating element and modality totals. The default "weighted" mode leans on a curated map that emphasises core factors (for example sun, moon, and ascendant weight 2.0, angles such as medium_coeli 1.5, personal planets 1.5, social planets 1.0, outers 0.5, and minor bodies 0.3β0.8). Provide distribution_method="pure_count" when you want every active point to contribute equally.
You can refine the weighting without rebuilding the dictionary: pass lowercase point names to custom_distribution_weights and use "__default__" to override the fallback value applied to entries that are not listed explicitly.
from kerykeion import AstrologicalSubjectFactory, ChartDataFactory
subject = AstrologicalSubjectFactory.from_birth_data(
"Sample", 1986, 4, 12, 8, 45,
lng=11.3426,
lat=44.4949,
tz_str="Europe/Rome",
online=False,
)
# Equal weighting: every active point counts once
pure_data = ChartDataFactory.create_natal_chart_data(
subject,
distribution_method="pure_count",
)
# Custom emphasis: boost the Sun, soften everything else
weighted_data = ChartDataFactory.create_natal_chart_data(
subject,
distribution_method="weighted",
custom_distribution_weights={
"sun": 3.0,
"__default__": 0.75,
},
)
print(pure_data.element_distribution.fire)
print(weighted_data.element_distribution.fire)All convenience helpers (create_synastry_chart_data, create_transit_chart_data, returns, and composites) forward the same keyword-only parameters, so you can keep a consistent weighting scheme across every chart type.
π Element/quality distribution guide: Distribution Documentation
By default, the zodiac type is Tropical. To use Sidereal, specify the sidereal mode:
johnny = AstrologicalSubjectFactory.from_birth_data(
"Johnny Depp", 1963, 6, 9, 0, 0,
lng=-87.1112,
lat=37.7719,
tz_str="America/Chicago",
online=False,
zodiac_type="Sidereal",
sidereal_mode="LAHIRI"
)π Sidereal mode examples: Sidereal Modes Guide
π Full list of supported sidereal modes: SiderealMode Schema
By default, houses are calculated using Placidus. Configure a different house system as follows:
johnny = AstrologicalSubjectFactory.from_birth_data(
"Johnny Depp", 1963, 6, 9, 0, 0,
lng=-87.1112,
lat=37.7719,
tz_str="America/Chicago",
online=False,
houses_system_identifier="M"
)π House system examples: House Systems Guide
π Full list of supported house systems: HouseSystemIdentifier Schema
So far all the available houses system in the Swiss Ephemeris are supported but the Gauquelin Sectors.
By default, Kerykeion uses the Apparent Geocentric perspective (the most standard in astrology). Other perspectives (e.g., Heliocentric) can be set this way:
johnny = AstrologicalSubjectFactory.from_birth_data(
"Johnny Depp", 1963, 6, 9, 0, 0,
lng=-87.1112,
lat=37.7719,
tz_str="America/Chicago",
online=False,
perspective_type="Heliocentric"
)π Perspective type examples: Perspective Type Guide
π Full list of supported perspective types: PerspectiveType Schema
Kerykeion provides several chart themes:
- Classic (default)
- Dark
- Dark High Contrast
- Light
- Strawberry
- Black & White (optimized for monochrome printing)
Each theme offers a distinct visual style, allowing you to choose the one that best suits your preferences or presentation needs. If you prefer more control over the appearance, you can opt not to set any theme, making it easier to customize the chart by overriding the default CSS variables.
π Theming guide with all examples: Theming Documentation
The Black & White theme renders glyphs, rings, and aspects in solid black on light backgrounds, designed for crisp B/W prints (PDF or paper) without sacrificing legibility.
Here's an example of how to set the theme:
from pathlib import Path
from kerykeion import AstrologicalSubjectFactory
from kerykeion.chart_data_factory import ChartDataFactory
from kerykeion.charts.chart_drawer import ChartDrawer
# Step 1: Create subject
dark_theme_subject = AstrologicalSubjectFactory.from_birth_data(
"John Lennon - Dark Theme", 1940, 10, 9, 18, 30,
lng=-2.9833,
lat=53.4,
tz_str="Europe/London",
online=False,
)
# Step 2: Pre-compute chart data
chart_data = ChartDataFactory.create_natal_chart_data(dark_theme_subject)
# Step 3: Create visualization with dark high contrast theme
dark_theme_natal_chart = ChartDrawer(chart_data=chart_data, theme="dark-high-contrast")
output_dir = Path("charts_output")
output_dir.mkdir(exist_ok=True)
dark_theme_natal_chart.save_svg(output_path=output_dir, filename="john-lennon-natal-dark-high-contrast")Create an AstrologicalSubjectModel from a UTC ISO 8601 string:
from kerykeion import AstrologicalSubjectFactory
subject = AstrologicalSubjectFactory.from_iso_utc_time(
name="Johnny Depp",
iso_utc_time="1963-06-09T05:00:00Z",
city="Owensboro",
nation="US",
lng=-87.1112,
lat=37.7719,
tz_str="America/Chicago",
online=False,
)
print(subject.iso_formatted_local_datetime)If you prefer automatic geocoding, set online=True and provide your GeoNames credentials via geonames_username.
π All initialization options: AstrologicalSubjectFactory Documentation
Kerykeion supports both True and Mean Lunar Nodes:
- True North Lunar Node:
"True_North_Lunar_Node" - True South Lunar Node:
"True_South_Lunar_Node" - Mean North Lunar Node:
"Mean_North_Lunar_Node" - Mean South Lunar Node:
"Mean_South_Lunar_Node"
By default, only the True nodes are active in charts and aspect calculations. To include the Mean nodes (or customize which nodes appear), pass the active_points parameter to the ChartDataFactory methods.
π ChartDataFactory documentation: ChartDataFactory Guide
Example:
from pathlib import Path
from kerykeion import AstrologicalSubjectFactory
from kerykeion.chart_data_factory import ChartDataFactory
from kerykeion.charts.chart_drawer import ChartDrawer
# Step 1: Create subject
subject = AstrologicalSubjectFactory.from_birth_data(
"John Lennon", 1940, 10, 9, 18, 30,
lng=-2.9833,
lat=53.4,
tz_str="Europe/London",
online=False,
)
# Step 2: Pre-compute chart data with custom active points including true nodes
chart_data = ChartDataFactory.create_natal_chart_data(
subject,
active_points=[
"Sun",
"Moon",
"Mercury",
"Venus",
"Mars",
"Jupiter",
"Saturn",
"Uranus",
"Neptune",
"Pluto",
"Mean_North_Lunar_Node",
"Mean_South_Lunar_Node",
"True_North_Lunar_Node",
"True_South_Lunar_Node",
"Ascendant",
"Medium_Coeli",
"Descendant",
"Imum_Coeli"
]
)
# Step 3: Create visualization
chart = ChartDrawer(chart_data=chart_data)
output_dir = Path("charts_output")
output_dir.mkdir(exist_ok=True)
chart.save_svg(output_path=output_dir, filename="johnny-depp-custom-points")You can serialize the astrological subject (the base data used throughout the library) to JSON:
from kerykeion import AstrologicalSubjectFactory
johnny = AstrologicalSubjectFactory.from_birth_data(
"Johnny Depp", 1963, 6, 9, 0, 0,
lng=-87.1112,
lat=37.7719,
tz_str="America/Chicago",
online=False,
)
print(johnny.model_dump_json(indent=2))π Data models and schemas: Schemas Documentation
- Main Website: kerykeion.net
- Getting Started: kerykeion.net/docs
- Examples Gallery: kerykeion.net/examples
- API Reference: kerykeion.net/pydocs
- Astrologer API Docs: kerykeion.net/astrologer-api
AstrologerStudio is a cloud-based astrology app built on top of Kerykeion.
Clone the repository or download the ZIP via the GitHub interface.
git clone https://github.com/g-battaglia/kerykeion.git
cd kerykeion
pip install -e ".[dev]"If you would like to incorporate Kerykeion's astrological features into your application, please reach out via email. Whether you need custom features, support, or specialized consulting, I am happy to discuss potential collaborations.
For commercial or closed-source applications, consider using the paid Astrologer API (RapidAPI plans & pricing) which provides REST endpoints for all Kerykeion functionality.
This project is covered under the AGPL-3.0 License. For detailed information, please see the LICENSE file. If you have questions, feel free to contact me at kerykeion.astrology@gmail.com.
As a rule of thumb, if you use this library in a project, you should open-source that project under a compatible license. Alternatively, if you wish to keep your source closed, consider using the paid Astrologer API, which is AGPL-3.0 compliant and also helps support the project.
Since the Astrologer API is an external third-party service, using it does not require your code to be open-source.
Contributions are welcome! Feel free to submit pull requests or report issues.
By submitting a contribution, you agree to assign the copyright of that contribution to the maintainer. The project stays openly available under the AGPL for everyone, while the re-licensing option helps sustain future development. Your authorship remains acknowledged in the commit history and release notes.
If using Kerykeion in published or academic work, please cite as follows:
Battaglia, G. (2025). Kerykeion: A Python Library for Astrological Calculations and Chart Generation.
https://github.com/g-battaglia/kerykeion