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

ArtifactPath
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:

ColumnPurpose
associated_message_typeReaction code (2000-3005); 0 = normal message
associated_message_guidGUID of the message being reacted to
associated_message_range_locationCharacter offset for multi-part reactions
associated_message_range_lengthCharacter length for multi-part reactions
is_from_meWho applied the reaction
handle_idFK to handle table for the person who reacted
dateWhen the reaction was applied

Reaction Codes

Added reactions (2000-2005):

CodeReactionVisual
2000LoveHeart
2001LikeThumbs up
2002DislikeThumbs down
2003LaughHa ha
2004EmphasizeDouble exclamation mark
2005QuestionQuestion mark

Removed reactions (3000-3005):

CodeReactionDescription
3000Removed LoveHeart reaction removed
3001Removed LikeThumbs up removed
3002Removed DislikeThumbs down removed
3003Removed LaughHa ha removed
3004Removed EmphasizeExclamation removed
3005Removed QuestionQuestion 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:

FormatExampleMeaning
<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 with handle table 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 message table. The text column for a reaction row is typically NULL or empty -- the semantic meaning is entirely in the associated_message_type code.
  • 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_guid in 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 VersionChanges
10.12 SierraTapback reactions introduced
13 VenturaNo schema changes; reactions follow attributedBody migration
15 SequoiaRCS messages can also receive tapback reactions

Tool Support

ToolCapability
macforDedicated reaction collection with parsed reaction types, direction, and handle resolution
sqlite3 CLIManual querying with WHERE clause on associated_message_type

References

Previous
Attachments