diff --git a/homeassistant/components/habitica/__init__.py b/homeassistant/components/habitica/__init__.py
index 502f52609ddbf1c91c0ebfab0d91f0cb025b2e3b..5843e14d63e166463477ffaf7f18cc393c9fbd35 100644
--- a/homeassistant/components/habitica/__init__.py
+++ b/homeassistant/components/habitica/__init__.py
@@ -30,6 +30,7 @@ CONFIG_SCHEMA = cv.config_entry_only_config_schema(DOMAIN)
 
 
 PLATFORMS = [
+    Platform.BINARY_SENSOR,
     Platform.BUTTON,
     Platform.CALENDAR,
     Platform.SENSOR,
diff --git a/homeassistant/components/habitica/binary_sensor.py b/homeassistant/components/habitica/binary_sensor.py
new file mode 100644
index 0000000000000000000000000000000000000000..bc79370ea63b279e7c28f45fe86718283d98b75e
--- /dev/null
+++ b/homeassistant/components/habitica/binary_sensor.py
@@ -0,0 +1,85 @@
+"""Binary sensor platform for Habitica integration."""
+
+from __future__ import annotations
+
+from collections.abc import Callable
+from dataclasses import dataclass
+from enum import StrEnum
+from typing import Any
+
+from homeassistant.components.binary_sensor import (
+    BinarySensorEntity,
+    BinarySensorEntityDescription,
+)
+from homeassistant.core import HomeAssistant
+from homeassistant.helpers.entity_platform import AddEntitiesCallback
+
+from .const import ASSETS_URL
+from .entity import HabiticaBase
+from .types import HabiticaConfigEntry
+
+
+@dataclass(kw_only=True, frozen=True)
+class HabiticaBinarySensorEntityDescription(BinarySensorEntityDescription):
+    """Habitica Binary Sensor Description."""
+
+    value_fn: Callable[[dict[str, Any]], bool | None]
+    entity_picture: Callable[[dict[str, Any]], str | None]
+
+
+class HabiticaBinarySensor(StrEnum):
+    """Habitica Entities."""
+
+    PENDING_QUEST = "pending_quest"
+
+
+def get_scroll_image_for_pending_quest_invitation(user: dict[str, Any]) -> str | None:
+    """Entity picture for pending quest invitation."""
+    if user["party"]["quest"].get("key") and user["party"]["quest"]["RSVPNeeded"]:
+        return f"inventory_quest_scroll_{user["party"]["quest"]["key"]}.png"
+    return None
+
+
+BINARY_SENSOR_DESCRIPTIONS: tuple[HabiticaBinarySensorEntityDescription, ...] = (
+    HabiticaBinarySensorEntityDescription(
+        key=HabiticaBinarySensor.PENDING_QUEST,
+        translation_key=HabiticaBinarySensor.PENDING_QUEST,
+        value_fn=lambda user: user["party"]["quest"]["RSVPNeeded"],
+        entity_picture=get_scroll_image_for_pending_quest_invitation,
+    ),
+)
+
+
+async def async_setup_entry(
+    hass: HomeAssistant,
+    config_entry: HabiticaConfigEntry,
+    async_add_entities: AddEntitiesCallback,
+) -> None:
+    """Set up the habitica binary sensors."""
+
+    coordinator = config_entry.runtime_data
+
+    async_add_entities(
+        HabiticaBinarySensorEntity(coordinator, description)
+        for description in BINARY_SENSOR_DESCRIPTIONS
+    )
+
+
+class HabiticaBinarySensorEntity(HabiticaBase, BinarySensorEntity):
+    """Representation of a Habitica binary sensor."""
+
+    entity_description: HabiticaBinarySensorEntityDescription
+
+    @property
+    def is_on(self) -> bool | None:
+        """If the binary sensor is on."""
+        return self.entity_description.value_fn(self.coordinator.data.user)
+
+    @property
+    def entity_picture(self) -> str | None:
+        """Return the entity picture to use in the frontend, if any."""
+        if entity_picture := self.entity_description.entity_picture(
+            self.coordinator.data.user
+        ):
+            return f"{ASSETS_URL}{entity_picture}"
+        return None
diff --git a/homeassistant/components/habitica/icons.json b/homeassistant/components/habitica/icons.json
index 617f08a4e58296d583a05fcf11bf8b3341d7524e..0698b85afe17ee9b2366136715668e39b09250be 100644
--- a/homeassistant/components/habitica/icons.json
+++ b/homeassistant/components/habitica/icons.json
@@ -135,6 +135,14 @@
           "on": "mdi:sleep"
         }
       }
+    },
+    "binary_sensor": {
+      "pending_quest": {
+        "default": "mdi:script-outline",
+        "state": {
+          "on": "mdi:script-text-outline"
+        }
+      }
     }
   },
   "services": {
diff --git a/homeassistant/components/habitica/strings.json b/homeassistant/components/habitica/strings.json
index 390dc3ba9ae182b9f55a89df358b6b53f4ac9e8c..45824c484e94fe5a316f2dc7f5b5e4af670fb2c2 100644
--- a/homeassistant/components/habitica/strings.json
+++ b/homeassistant/components/habitica/strings.json
@@ -38,6 +38,11 @@
     }
   },
   "entity": {
+    "binary_sensor": {
+      "pending_quest": {
+        "name": "Pending quest invitation"
+      }
+    },
     "button": {
       "run_cron": {
         "name": "Start my day"
diff --git a/tests/components/habitica/fixtures/quest_invitation_off.json b/tests/components/habitica/fixtures/quest_invitation_off.json
new file mode 100644
index 0000000000000000000000000000000000000000..f862a85c7c45d8857879efefa2dc57d693f0e95a
--- /dev/null
+++ b/tests/components/habitica/fixtures/quest_invitation_off.json
@@ -0,0 +1,64 @@
+{
+  "data": {
+    "api_user": "test-api-user",
+    "profile": { "name": "test-user" },
+    "stats": {
+      "buffs": {
+        "str": 0,
+        "int": 0,
+        "per": 0,
+        "con": 0,
+        "stealth": 0,
+        "streaks": false,
+        "seafoam": false,
+        "shinySeed": false,
+        "snowball": false,
+        "spookySparkles": false
+      },
+      "hp": 0,
+      "mp": 50.89999999999998,
+      "exp": 737,
+      "gp": 137.62587214609795,
+      "lvl": 38,
+      "class": "wizard",
+      "maxHealth": 50,
+      "maxMP": 166,
+      "toNextLevel": 880,
+      "points": 5
+    },
+    "preferences": {
+      "sleep": false,
+      "automaticAllocation": true,
+      "disableClasses": false
+    },
+    "flags": {
+      "classSelected": true
+    },
+    "tasksOrder": {
+      "rewards": ["5e2ea1df-f6e6-4ba3-bccb-97c5ec63e99b"],
+      "todos": [
+        "88de7cd9-af2b-49ce-9afd-bf941d87336b",
+        "2f6fcabc-f670-4ec3-ba65-817e8deea490",
+        "1aa3137e-ef72-4d1f-91ee-41933602f438",
+        "86ea2475-d1b5-4020-bdcc-c188c7996afa"
+      ],
+      "dailys": [
+        "f21fa608-cfc6-4413-9fc7-0eb1b48ca43a",
+        "bc1d1855-b2b8-4663-98ff-62e7b763dfc4",
+        "e97659e0-2c42-4599-a7bb-00282adc410d",
+        "564b9ac9-c53d-4638-9e7f-1cd96fe19baa",
+        "f2c85972-1a19-4426-bc6d-ce3337b9d99f",
+        "2c6d136c-a1c3-4bef-b7c4-fa980784b1e1"
+      ],
+      "habits": ["1d147de6-5c02-4740-8e2f-71d3015a37f4"]
+    },
+    "party": {
+      "quest": {
+        "RSVPNeeded": false,
+        "key": null
+      }
+    },
+    "needsCron": true,
+    "lastCron": "2024-09-21T22:01:55.586Z"
+  }
+}
diff --git a/tests/components/habitica/fixtures/user.json b/tests/components/habitica/fixtures/user.json
index a10ce354f442d0b55d1428c867bfaf9eb58b4190..818f4ed4eda864c7e3e41d2b550f5dd158b3e493 100644
--- a/tests/components/habitica/fixtures/user.json
+++ b/tests/components/habitica/fixtures/user.json
@@ -52,6 +52,12 @@
       ],
       "habits": ["1d147de6-5c02-4740-8e2f-71d3015a37f4"]
     },
+    "party": {
+      "quest": {
+        "RSVPNeeded": true,
+        "key": "dustbunnies"
+      }
+    },
     "needsCron": true,
     "lastCron": "2024-09-21T22:01:55.586Z"
   }
diff --git a/tests/components/habitica/snapshots/test_binary_sensor.ambr b/tests/components/habitica/snapshots/test_binary_sensor.ambr
new file mode 100644
index 0000000000000000000000000000000000000000..c18f8f551c9212370a18beb6b2bf59c83b50c87e
--- /dev/null
+++ b/tests/components/habitica/snapshots/test_binary_sensor.ambr
@@ -0,0 +1,48 @@
+# serializer version: 1
+# name: test_binary_sensors[binary_sensor.test_user_pending_quest_invitation-entry]
+  EntityRegistryEntrySnapshot({
+    'aliases': set({
+    }),
+    'area_id': None,
+    'capabilities': None,
+    'config_entry_id': <ANY>,
+    'device_class': None,
+    'device_id': <ANY>,
+    'disabled_by': None,
+    'domain': 'binary_sensor',
+    'entity_category': None,
+    'entity_id': 'binary_sensor.test_user_pending_quest_invitation',
+    'has_entity_name': True,
+    'hidden_by': None,
+    'icon': None,
+    'id': <ANY>,
+    'labels': set({
+    }),
+    'name': None,
+    'options': dict({
+    }),
+    'original_device_class': None,
+    'original_icon': None,
+    'original_name': 'Pending quest invitation',
+    'platform': 'habitica',
+    'previous_unique_id': None,
+    'supported_features': 0,
+    'translation_key': <HabiticaBinarySensor.PENDING_QUEST: 'pending_quest'>,
+    'unique_id': '00000000-0000-0000-0000-000000000000_pending_quest',
+    'unit_of_measurement': None,
+  })
+# ---
+# name: test_binary_sensors[binary_sensor.test_user_pending_quest_invitation-state]
+  StateSnapshot({
+    'attributes': ReadOnlyDict({
+      'entity_picture': 'https://habitica-assets.s3.amazonaws.com/mobileApp/images/inventory_quest_scroll_dustbunnies.png',
+      'friendly_name': 'test-user Pending quest invitation',
+    }),
+    'context': <ANY>,
+    'entity_id': 'binary_sensor.test_user_pending_quest_invitation',
+    'last_changed': <ANY>,
+    'last_reported': <ANY>,
+    'last_updated': <ANY>,
+    'state': 'on',
+  })
+# ---
diff --git a/tests/components/habitica/test_binary_sensor.py b/tests/components/habitica/test_binary_sensor.py
new file mode 100644
index 0000000000000000000000000000000000000000..5b19cd008bf5b8f3e810b269f4ef549dfb347f6b
--- /dev/null
+++ b/tests/components/habitica/test_binary_sensor.py
@@ -0,0 +1,80 @@
+"""Tests for the Habitica binary sensor platform."""
+
+from collections.abc import Generator
+from unittest.mock import patch
+
+import pytest
+from syrupy.assertion import SnapshotAssertion
+
+from homeassistant.components.habitica.const import ASSETS_URL, DEFAULT_URL, DOMAIN
+from homeassistant.config_entries import ConfigEntryState
+from homeassistant.const import STATE_OFF, STATE_ON, Platform
+from homeassistant.core import HomeAssistant
+from homeassistant.helpers import entity_registry as er
+
+from tests.common import MockConfigEntry, load_json_object_fixture, snapshot_platform
+from tests.test_util.aiohttp import AiohttpClientMocker
+
+
+@pytest.fixture(autouse=True)
+def binary_sensor_only() -> Generator[None]:
+    """Enable only the binarty sensor platform."""
+    with patch(
+        "homeassistant.components.habitica.PLATFORMS",
+        [Platform.BINARY_SENSOR],
+    ):
+        yield
+
+
+@pytest.mark.usefixtures("mock_habitica")
+async def test_binary_sensors(
+    hass: HomeAssistant,
+    config_entry: MockConfigEntry,
+    snapshot: SnapshotAssertion,
+    entity_registry: er.EntityRegistry,
+) -> None:
+    """Test setup of the Habitica binary sensor platform."""
+
+    config_entry.add_to_hass(hass)
+    await hass.config_entries.async_setup(config_entry.entry_id)
+    await hass.async_block_till_done()
+
+    assert config_entry.state is ConfigEntryState.LOADED
+
+    await snapshot_platform(hass, entity_registry, snapshot, config_entry.entry_id)
+
+
+@pytest.mark.parametrize(
+    ("fixture", "entity_state", "entity_picture"),
+    [
+        ("user", STATE_ON, f"{ASSETS_URL}inventory_quest_scroll_dustbunnies.png"),
+        ("quest_invitation_off", STATE_OFF, None),
+    ],
+)
+async def test_pending_quest_states(
+    hass: HomeAssistant,
+    config_entry: MockConfigEntry,
+    aioclient_mock: AiohttpClientMocker,
+    fixture: str,
+    entity_state: str,
+    entity_picture: str | None,
+) -> None:
+    """Test states of pending quest sensor."""
+
+    aioclient_mock.get(
+        f"{DEFAULT_URL}/api/v3/user",
+        json=load_json_object_fixture(f"{fixture}.json", DOMAIN),
+    )
+    aioclient_mock.get(f"{DEFAULT_URL}/api/v3/tasks/user", json={"data": []})
+
+    config_entry.add_to_hass(hass)
+    await hass.config_entries.async_setup(config_entry.entry_id)
+    await hass.async_block_till_done()
+
+    assert config_entry.state is ConfigEntryState.LOADED
+
+    assert (
+        state := hass.states.get("binary_sensor.test_user_pending_quest_invitation")
+    )
+    assert state.state == entity_state
+    assert state.attributes.get("entity_picture") == entity_picture