Skip to content

EmpireCore

A fully typed Python client for Goodgame Empire that follows the game's own client. Read your account and castles, react to incoming attacks and other events as they happen, send armies and spies, and run several accounts at once.

Get started Guides

import time

from empire_core import EmpireClient, Movement


def warn(attack: Movement) -> None:
    print(f"Attack from {attack.source_player_name}, "
          f"landing in {attack.time_remaining}s")


with EmpireClient(
    username="you", password="...", keep_session=True
) as client:
    client.login()

    for castle in client.castle.get_all():
        res = client.castle.get_resources(castle.castle_id)
        print(f"{castle.castle_name}: {res.wood:,} wood, "
              f"{res.stone:,} stone, {res.food:,} food")

    client.state.on_incoming_attack(warn)
    time.sleep(3600)
Ironhold: 12,400 wood, 9,850 stone, 21,300 food
Attack from Redmane, landing in 1742s

EmpireCore is in alpha

The API is not stable yet, and a minor release may break it; the changelog lists every change that does. EmpireCore talks to the live game servers, so use it at your own risk and with the game's terms of service in mind.

16 servicescastle, army, attack, spy, map and more
Python 3.10–3.14typed, with a py.typed marker
  • Typed end to end

    Pydantic models for every request and reply, with readable field names, so your editor and type checker know every field.

  • Follows the real client

    Requests are built the way the game client builds them, and each model names the client code it mirrors.

  • Live state and events

    A background thread keeps your account's state current. Register callbacks for incoming attacks, chat and more, or stream them with asyncio.

  • Stays logged in

    With keep_session=True the client logs back in after a dropped connection, and your callbacks keep firing.

  • Several accounts

    AccountPool hands out one logged-in client per account, safely across threads.

  • Clear errors

    One EmpireError base for everything the library raises. An empty list always means there was nothing there.

Install

uv add empire-core        # or: pip install empire-core

Pin a minor line, for example empire-core>=0.48,<0.49, since a minor release may change the API. Next, Getting started walks through logging in, reading your castles and the errors to expect.