Messages
Tapback Reactions
Overview
Tapback reactions (also called "tapbacks") are the heart, thumbs up, thumbs down, laugh, exclamation, and question mark responses that users can apply to individual messages in iMessage conversations. Forensically, reactions are stored as regular entries in the message table but with a non-zero associated_message_type value that identifies the reaction type. Each reaction links back to the original message via the associated_message_guid column.
Reactions provide evidence of user engagement with specific messages and can demonstrate that a user not only received but actively interacted with a particular communication.
File Locations
| Artifact | Path |
|---|---|
| Reactions | ~/Library/Messages/chat.db (message table, filtered by associated_message_type) |
Reactions are not stored in a separate table. They exist as rows in the message table where associated_message_type is between 2000 and 3005.
Database Schema
Reactions use the standard message table. The relevant columns are:
| Column | Purpose |
|---|---|
associated_message_type | Reaction code (2000-3005); 0 = normal message |
associated_message_guid | GUID of the message being reacted to |
associated_message_range_location | Character offset for multi-part reactions |
associated_message_range_length | Character length for multi-part reactions |
is_from_me | Who applied the reaction |
handle_id | FK to handle table for the person who reacted |
date | When the reaction was applied |
Reaction Codes
Added reactions (2000-2005):
| Code | Reaction | Visual |
|---|---|---|
| 2000 | Love | Heart |
| 2001 | Like | Thumbs up |
| 2002 | Dislike | Thumbs down |
| 2003 | Laugh | Ha ha |
| 2004 | Emphasize | Double exclamation mark |
| 2005 | Question | Question mark |
Removed reactions (3000-3005):
| Code | Reaction | Description |
|---|---|---|
| 3000 | Removed Love | Heart reaction removed |
| 3001 | Removed Like | Thumbs up removed |
| 3002 | Removed Dislike | Thumbs down removed |
| 3003 | Removed Laugh | Ha ha removed |
| 3004 | Removed Emphasize | Exclamation removed |
| 3005 | Removed Question | Question mark removed |
A "removed" reaction (3000-3005) indicates the user explicitly retracted a previously applied reaction. The offset between added and removed codes is always 1000.
Associated Message GUID Formats
The associated_message_guid column uses three formats:
| Format | Example | Meaning |
|---|---|---|
<guid> | A1B2C3D4-... | Standard reference to a message |
p:<index>/<guid> | p:0/A1B2C3D4-... | Reaction on a specific part of a multi-part message |
bp:<guid> | bp:A1B2C3D4-... | Reference without part-specific text |
Key Fields for Analysis
associated_message_type: The reaction code. Any non-zero value in the range 2000-3005 identifies this row as a reaction rather than a regular message.associated_message_guid: Links the reaction to the specific message it responds to.is_from_me: Whether the local user applied the reaction (1) or someone else did (0).handle_id: The handle of the person who applied the reaction (join withhandletable for phone/email).date: When the reaction was applied (Core Data nanoseconds).
Forensic Query
-- Extract all reactions with context
SELECT
datetime(m.date / 1000000000 + 978307200, 'unixepoch') AS reaction_date,
CASE m.associated_message_type
WHEN 2000 THEN 'Love'
WHEN 2001 THEN 'Like'
WHEN 2002 THEN 'Dislike'
WHEN 2003 THEN 'Laugh'
WHEN 2004 THEN 'Emphasize'
WHEN 2005 THEN 'Question'
WHEN 3000 THEN 'Removed Love'
WHEN 3001 THEN 'Removed Like'
WHEN 3002 THEN 'Removed Dislike'
WHEN 3003 THEN 'Removed Laugh'
WHEN 3004 THEN 'Removed Emphasize'
WHEN 3005 THEN 'Removed Question'
END AS reaction_type,
CASE WHEN m.is_from_me = 1 THEN 'LOCAL USER' ELSE h.id END AS reactor,
m.associated_message_guid AS target_message,
orig.text AS original_text
FROM message m
LEFT JOIN handle h ON m.handle_id = h.ROWID
LEFT JOIN message orig ON m.associated_message_guid = orig.guid
WHERE m.associated_message_type BETWEEN 2000 AND 3005
ORDER BY m.date;
Timestamps
Reaction timestamps use Core Data nanoseconds (nanoseconds since 2001-01-01 00:00:00 UTC), the same format as all other message.date values.
Analysis Notes
- Reactions are messages: Each reaction creates a new row in the
messagetable. Thetextcolumn for a reaction row is typically NULL or empty -- the semantic meaning is entirely in theassociated_message_typecode. - Removed reactions: A code in the 3000-3005 range means the user retracted their reaction. This is forensically significant because it shows the user first reacted, then deliberately removed that reaction.
- Counting active reactions: To determine the current reaction state of a message, you must replay all reaction events (adds and removes) for that
associated_message_guidin chronological order. - Multi-part references: The
p:<index>/<guid>format targets a specific part of a message that contains both text and attachments. The index refers to the part number (0-based). - Group chat reactions: In group chats, reactions from different participants each create separate message rows, all pointing to the same
associated_message_guid.
Version Differences
| macOS Version | Changes |
|---|---|
| 10.12 Sierra | Tapback reactions introduced |
| 13 Ventura | No schema changes; reactions follow attributedBody migration |
| 15 Sequoia | RCS messages can also receive tapback reactions |
Tool Support
| Tool | Capability |
|---|---|
| macfor | Dedicated reaction collection with parsed reaction types, direction, and handle resolution |
| sqlite3 CLI | Manual querying with WHERE clause on associated_message_type |