Baileyspy is a comprehensive Python wrapper for the Baileys WhatsApp library, providing a robust and easy-to-use interface for WhatsApp automation and bot development. Built on top of the powerful Baileys JavaScript library, Baileyspy brings Pythonic elegance to WhatsApp bot development while maintaining full feature parity with the original Baileys library.
- WhatsApp Web Protocol Integration: Full compatibility with WhatsApp Web's latest protocol version (2.3000.1028620558)
- QR Code Authentication: Seamless QR code scanning and authentication process
- Custom Pairing Codes: Support for custom pairing codes (e.g., 'AAAA-AAAA') with Baileys's pairing system
- Session Persistence: Automatic session management and restoration
- Multi-Device Support: Works with linked devices, optimized for iOS/Safari
- Signal Protocol Integration: Built-in libsignal-xeuka for enhanced encryption
- Text Messages: Send and receive text messages with full formatting support
- Media Support: Send images, videos, documents, audio files, and stickers
- Interactive Messages: Create buttons, lists, and polls for enhanced user engagement
- Message Reactions: Add reactions to messages with emoji support
- Ephemeral Messages: Send disappearing messages with configurable timeouts
- Reply System: Reply to specific messages with threading support
- Typing Indicators: Send and receive typing status notifications
- Message Status: Track message delivery, read receipts, and status
- Group Creation: Create groups with customizable settings
- Member Management: Add, remove, promote, and demote group participants
- Group Settings: Configure group name, description, and permissions
- Group Pictures: Set and manage group profile pictures
- Invite Links: Generate, revoke, and use group invite links
- Group Polls: Create and manage polls within groups
- Group Admin Features: Full administrative control over group operations
- Voice Calls: Initiate voice calls to any WhatsApp user
- Call Control: Accept, reject, and manage ongoing calls
- Call Status: Real-time call status monitoring and management
- Call History: Track and retrieve call history information
- Call Statistics: Detailed call analytics and reporting
- Secure Pairing: Safe device pairing with custom pairing codes
- Session Management: Secure session storage and management
- Token Validation: Automatic token validation and renewal
- Device Linking: Support for multiple device linking scenarios
- File Upload: Support for various media formats with automatic type detection
- Image Processing: Advanced image handling with quality optimization
- Video Processing: Video file handling with duration and metadata extraction
- Document Support: PDF, Office documents, and various file formats
- Profile Management: Set profile pictures and group pictures
- Media Download: Download media from incoming messages
- Event System: Comprehensive event handling for all WhatsApp activities
- Async/Await Support: Full asynchronous programming support
- Logging: Detailed logging and debugging capabilities
- Error Handling: Robust error handling and recovery mechanisms
- Type Hints: Full type annotation support for better development experience
Before installing Baileyspy, ensure you have:
- Python 3.14.0 or higher
- Node.js 14+ (required for Baileys backend)
- npm or yarn (for Baileys dependencies)
pip install git+https://github.com/terastudio-org/Baileyspy.gitgit clone https://github.com/angstvorfrauen/Baileys.git
cd Baileys
pip install -e .Baileyspy requires the following Python packages:
requests>=2.25.0
websocket-client>=1.3.0
aiofiles>=0.7.0
python-dotenv>=0.19.0
Optional dependencies for enhanced functionality:
pillow>=8.0.0
beautifulsoup4>=4.9.0
jsonschema>=3.2.0
colorama>=0.4.4
rich>=12.0.0
import asyncio
from baileyspy import BaileysClient
async def main():
# Initialize the client
client = BaileysClient(session_id="my_bot")
# Connect to WhatsApp
connection_info = await client.connect()
if connection_info['status'] == 'qr_required':
print("Scan the QR code to connect:")
print(f"QR Code: {connection_info['qr_code']}")
# Wait for connection (in a real scenario, user would scan QR)
connection_info = await client.connect()
if connection_info['status'] == 'connected':
print(f"Connected as: {connection_info['phone_number']}")
# Send a message
await client.send_message("1234567890@s.whatsapp.net", "Hello from Baileyspy!")
# Create a group
groups = await client.get_groups()
print(f"Available groups: {len(groups)}")
# Run the bot
asyncio.run(main())import asyncio
from baileyspy import BaileysClient
async def on_message(client, message):
"""Handle incoming messages."""
if message['from_me']:
return # Skip self-messages
sender = message['sender']
content = message['content']
# Respond to commands
if content.startswith('!help'):
help_text = """
๐ค Baileyspy Bot Commands:
!help - Show this help message
!ping - Check bot status
!time - Current time
!groups - List available groups
"""
await client.send_message(sender, help_text)
elif content.startswith('!ping'):
await client.send_message(sender, "๐ Pong! Bot is online.")
elif content.startswith('!time'):
from datetime import datetime
current_time = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
await client.send_message(sender, f"๐ Current time: {current_time}")
async def on_connect(client, info):
"""Handle connection events."""
print(f"Connected to WhatsApp: {info['phone_number']}")
print("Bot is ready to receive messages!")
async def main():
client = BaileysClient(session_id="event_bot")
# Register event handlers
client.on('message', on_message)
client.on('connected', on_connect)
# Connect and start listening
await client.connect()
# Keep the bot running
try:
while True:
await asyncio.sleep(1)
except KeyboardInterrupt:
await client.disconnect()
asyncio.run(main())Baileyspy provides extensive configuration options:
config = {
'session_dir': 'sessions/my_bot',
'qr_timeout': 60,
'message_timeout': 30,
'pairing_code': 'BBBB-CCCC',
'is_bot': True,
'connection_retries': 5,
'max_message_size': 16 * 1024 * 1024, # 16MB
'media_quality': 'high',
'enable_logging': True,
'log_level': 'INFO'
}
client = BaileysClient(session_id="configured_bot", config=config)# Simple text message
await client.send_message("jid@s.whatsapp.net", "Hello World!")
# Message with options
await client.send_message(
"jid@s.whatsapp.net",
"Bold message",
quoted_message_id="message_id",
mentioned_jids=["jid@s.whatsapp.net"],
view_once=True
)# Send image
await client.send_image("jid@s.whatsapp.net", "path/to/image.jpg",
caption="Check this out!")
# Send video
await client.send_video("jid@s.whatsapp.net", "path/to/video.mp4",
caption="Cool video!")
# Send document
await client.send_document("jid@s.whatsapp.net", "path/to/document.pdf")
# Send audio
await client.send_audio("jid@s.whatsapp.net", "path/to/audio.mp3",
audio_type="voice")
# Send sticker
await client.send_sticker("jid@s.whatsapp.net", "path/to/sticker.webp")from baileyspy.messages import create_button, create_list_item
# Buttons
buttons = [
create_button("Yes", "yes"),
create_button("No", "no"),
create_button("Maybe", "maybe")
]
await client.send_interactive_message(
"jid@s.whatsapp.net",
"Do you agree?",
buttons=buttons
)
# List messages
list_items = [
create_list_item("Option 1", "Description 1"),
create_list_item("Option 2", "Description 2"),
create_list_item("Option 3", "Description 3")
]
await client.send_interactive_message(
"jid@s.whatsapp.net",
"Choose an option:",
list_items=list_items
)
# Poll messages
poll_options = ["Yes", "No", "Maybe"]
await client.send_poll_message(
"jid@s.whatsapp.net",
"Do you like Python?",
poll_options,
multiple_answers=False
)# 24-hour ephemeral message
await client.send_ephemeral_message(
"jid@s.whatsapp.net",
"This message will disappear in 24 hours",
ephemeral_duration=24 * 60 * 60
)# Create a group
participants = ["jid1@s.whatsapp.net", "jid2@s.whatsapp.net"]
group_info = await client.create_group(
name="My Awesome Group",
participants=participants,
description="A group for awesome people"
)
# Get all groups
groups = await client.get_groups()
for group in groups:
print(f"Group: {group['name']} ({group['member_count']} members)")
# Add participants to group
await client.add_participants(
group_info['group_id'],
["jid3@s.whatsapp.net", "jid4@s.whatsapp.net"]
)
# Set group picture
await client.set_group_picture(
group_info['group_id'],
"path/to/group_picture.jpg"
)
# Get invite link
invite_info = await client.get_invite_link(group_info['group_id'])
print(f"Join link: {invite_info['invite_link']}")
# Join group via invite link
joined_info = await client.join_group(invite_info['invite_link'])# Initiate a call
call_info = await client.offer_call("jid@s.whatsapp.net")
print(f"Call initiated: {call_info['call_id']}")
# Accept a call
await client.accept_call(call_info['call_id'])
# End a call
await client.end_call(call_info['call_id'])
# Get call history
call_history = await client.get_call_history(limit=10)
for call in call_history:
print(f"Call with {call['jid']}: {call['duration']} seconds")# Set profile picture
await client.set_profile_picture("path/to/profile.jpg")
# Download media from message
download_info = await client.download_media(
message_id="message_id",
output_path="downloaded_media"
)
# Get media information
media_info = client.media_handler.get_media_info("path/to/media.jpg")
print(f"Media type: {media_info['media_type']}")
print(f"File size: {media_info['file_size']} bytes")# Request custom pairing code
pairing_info = await client.pairing_manager.request_pairing_code(
number="1234567890",
code="DDDD-EEEE"
)
print(f"Pairing code: {pairing_info['pairing_code']}")
# Verify pairing code
await client.pairing_manager.verify_pairing_code(
pairing_info['pairing_id'],
"DDDD-EEEE"
)
# Complete pairing
auth_info = await client.pairing_manager.complete_pairing(
pairing_info['pairing_id']
)
print(f"Device paired: {auth_info['device_id']}")async def custom_message_handler(client, message):
"""Custom message processing."""
# Implement your custom logic here
pass
async def custom_call_handler(event_type, call_info):
"""Custom call event handling."""
# Handle call events
if event_type == 'incoming_call':
print(f"Incoming call from {call_info['jid']}")
elif event_type == 'call_ended':
print(f"Call ended, duration: {call_info['duration']}s")
# Register custom handlers
client.message_handler.register_message_handler(custom_message_handler)
client.call_manager.register_call_handler(custom_call_handler)async with BaileysClient("context_bot") as client:
connection_info = await client.connect()
if connection_info['status'] == 'connected':
await client.send_message("jid@s.whatsapp.net", "Hello from context manager!")
# Connection automatically closed when exiting context# Save session to file
await client.save_session("custom_session.json")
# Load session from file
await client.load_session("custom_session.json")
# Get connection info
info = client.get_connection_info()
print(f"Connected: {info['is_connected']}")
print(f"Phone: {info['phone_number']}")from baileyspy.utils import Utils
utils = Utils()
# Format phone numbers
jid = utils.format_phone_number("1234567890", country_code="US")
print(jid) # "11234567890@s.whatsapp.net"
# Validate JIDs
is_valid = utils.is_valid_whatsapp_jid("1234567890@s.whatsapp.net")
print(is_valid) # True
# Format message for display
message_data = {"type": "image", "caption": "Beautiful sunset"}
display_text = utils.format_message_for_display(message_data)
print(display_text) # "[Image] Beautiful sunset"
# Generate unique message ID
msg_id = utils.generate_message_id()
print(msg_id) # "msg_1634567890123_abcdef12"baileyspy/
โโโ __init__.py # Package initialization and exports
โโโ client.py # Main BaileysClient class
โโโ connection.py # Connection and authentication management
โโโ messages.py # Message sending and receiving
โโโ groups.py # Group management operations
โโโ call_manager.py # Voice call handling
โโโ pairing.py # Device pairing and authentication
โโโ media.py # Media file handling
โโโ utils.py # Utility functions and helpers
โโโ requirements.txt # Python dependencies
โโโ setup.py # Package installation script
- BaileysClient: Main client class that orchestrates all operations
- ConnectionManager: Handles WhatsApp Web connection and authentication
- MessageHandler: Manages message sending, receiving, and formatting
- GroupManager: Provides group creation and management functionality
- CallManager: Handles voice call operations and call state management
- PairingManager: Manages device pairing and custom pairing codes
- MediaHandler: Processes media files and profile picture operations
- Utils: Utility functions for common operations and data processing
- Session Security: Always store sessions in secure directories with appropriate permissions
- API Keys: Never commit API keys or authentication tokens to version control
- Rate Limiting: Implement rate limiting to avoid being flagged as spam
- Content Filtering: Filter and validate all user content before processing
- Error Handling: Implement proper error handling to prevent information leakage
Use environment variables for sensitive configuration:
import os
from dotenv import load_dotenv
load_dotenv()
config = {
'session_dir': os.getenv('BAILEYS_SESSION_DIR', 'sessions/default'),
'api_key': os.getenv('WHATSAPP_API_KEY'),
'max_retries': int(os.getenv('MAX_RETRIES', '3'))
}import asyncio
import logging
from datetime import datetime
from baileyspy import BaileysClient, create_client
# Configure logging
logging.basicConfig(level=logging.INFO)
logger = logging.getLogger(__name__)
class WhatsAppBot:
def __init__(self, session_id="my_bot"):
self.client = create_client(session_id)
self.setup_handlers()
def setup_handlers(self):
"""Setup event handlers."""
self.client.on('message', self.handle_message)
self.client.on('connected', self.handle_connect)
self.client.on('disconnected', self.handle_disconnect)
async def handle_message(self, client, message):
"""Handle incoming messages."""
try:
if message.get('from_me'):
return
sender = message['sender']
content = message.get('content', '')
# Simple command system
if content.startswith('!time'):
current_time = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
await client.send_message(sender, f"๐ {current_time}")
elif content.startswith('!stats'):
groups = await client.get_groups()
info = client.get_connection_info()
stats_text = f"""
๐ Bot Statistics:
โข Connected: {info['is_connected']}
โข Phone: {info['phone_number']}
โข Groups: {len(groups)}
โข Session: {info['session_id']}
"""
await client.send_message(sender, stats_text)
elif content.startswith('!groups'):
groups = await client.get_groups()
if groups:
group_list = "\n".join([
f"โข {group['name']} ({group['member_count']} members)"
for group in groups[:5]
])
await client.send_message(sender, f"๐ Your groups:\n{group_list}")
else:
await client.send_message(sender, "โ No groups found")
elif content.startswith('!ping'):
await client.send_message(sender, "๐ Pong! Bot is online and ready!")
elif content.startswith('!help'):
help_text = """
๐ค **WhatsApp Bot Commands**
๐ `!time` - Show current time
๐ `!stats` - Show bot statistics
๐ `!groups` - List your groups
๐ `!ping` - Check bot status
โ `!help` - Show this help message
*Powered by Baileyspy* ๐
"""
await client.send_message(sender, help_text)
# Echo non-command messages (demo)
else:
response = f"๐ I received: '{content}'\n\nType !help for available commands!"
await client.send_message(sender, response)
except Exception as e:
logger.error(f"Error handling message: {e}")
await client.send_message(sender, "โ An error occurred while processing your message.")
async def handle_connect(self, client, info):
"""Handle connection event."""
logger.info(f"Connected to WhatsApp: {info['phone_number']}")
print(f"โ
Bot connected as: {info['phone_number']}")
print("๐ค Bot is ready to receive messages!")
print("๐ฑ Send '!help' to this number to see available commands.")
async def handle_disconnect(self, client, info):
"""Handle disconnection event."""
logger.warning(f"Disconnected from WhatsApp: {info}")
async def start(self):
"""Start the bot."""
try:
print("๐ Starting WhatsApp Bot...")
connection_info = await self.client.connect()
if connection_info['status'] == 'qr_required':
print("๐ฑ Please scan the QR code to connect:")
print(f"QR Code: {connection_info['qr_code']}")
# Wait for QR scan
while True:
try:
connection_info = await self.client.connect()
if connection_info['status'] == 'connected':
break
await asyncio.sleep(2)
except Exception as e:
logger.error(f"Connection check failed: {e}")
await asyncio.sleep(5)
# Keep bot running
try:
while True:
await asyncio.sleep(10)
except KeyboardInterrupt:
print("\n๐ Bot stopped by user")
finally:
await self.client.disconnect()
except Exception as e:
logger.error(f"Bot failed to start: {e}")
raise
# Run the bot
if __name__ == "__main__":
bot = WhatsAppBot()
asyncio.run(bot.start())import asyncio
from baileyspy import BaileysClient
class MediaBot:
def __init__(self):
self.client = BaileysClient("media_bot")
self.setup_handlers()
def setup_handlers(self):
self.client.on('message', self.handle_media_request)
async def handle_media_request(self, client, message):
"""Handle media-related requests."""
if message.get('from_me'):
return
sender = message['sender']
content = message.get('content', '')
if content.startswith('!image'):
# Send an image
await client.send_image(
sender,
"examples/sample_image.jpg",
caption="๐ผ๏ธ Sample image sent via Baileyspy!"
)
elif content.startswith('!video'):
# Send a video
await client.send_video(
sender,
"examples/sample_video.mp4",
caption="๐ฌ Sample video sent via Baileyspy!"
)
elif content.startswith('!profile'):
# Set profile picture (demo)
await client.send_message(
sender,
"๐ธ To set your profile picture, use:\n!set_profile path/to/image.jpg"
)
elif content.startswith('!set_profile'):
# Parse file path from message
parts = content.split(' ', 1)
if len(parts) > 1:
image_path = parts[1].strip()
try:
await client.set_profile_picture(image_path)
await client.send_message(sender, "โ
Profile picture updated!")
except Exception as e:
await client.send_message(sender, f"โ Error: {str(e)}")
else:
await client.send_message(sender, "๐ Usage: !set_profile path/to/image.jpg")
async def main():
bot = MediaBot()
await bot.client.connect()
print("๐ธ Media Bot ready!")
# Keep running
try:
while True:
await asyncio.sleep(1)
except KeyboardInterrupt:
await bot.client.disconnect()
asyncio.run(main())We welcome contributions to Baileyspy! Here's how you can help:
-
Fork the repository
-
Clone your fork:
git clone https://github.com/your-username/Baileys.git cd Baileys -
Create a virtual environment:
python -m venv venv source venv/bin/activate # On Windows: venv\Scripts\activate
-
Install development dependencies:
pip install -e .[dev]
-
Install pre-commit hooks:
pre-commit install
- Code Style: Follow PEP 8 and use
blackfor formatting - Type Hints: Add type hints to all new functions and classes
- Documentation: Add docstrings to all public functions
- Testing: Write tests for new features
- Commits: Use conventional commit messages
Run tests with:
# Run all tests
pytest
# Run with coverage
pytest --cov=baileyspy
# Run specific test file
pytest tests/test_client.py- Create a feature branch
- Make your changes
- Add tests for new functionality
- Update documentation
- Submit a pull request
This project is licensed under the MIT License - see the LICENSE file for details.
- Baileys Library: angstvorfrauen/Baileys - The powerful JavaScript WhatsApp library this wrapper is built upon
- WhatsApp Web: For providing the protocol that enables automation
- Python Community: For the excellent libraries and tools that make this wrapper possible
- Documentation: Check this README and the Wiki
- Issues: Report bugs and request features in GitHub Issues
- Discussions: Join discussions in GitHub Discussions
Q: Connection fails with QR code A: Ensure your internet connection is stable and try again. The QR code expires after a short time.
Q: Media files not sending A: Check file size limits (16MB for media, 100MB for documents) and supported formats.
Q: Bot stops responding A: Check the logs for error messages and ensure your session file is not corrupted.
Enable detailed logging:
import logging
logging.basicConfig(level=logging.DEBUG)
client = BaileysClient("debug_bot")- Enhanced media processing capabilities
- Improved error handling and recovery
- Additional message types support
- Performance optimizations
- Webhook support for real-time events
- Database integration for message storage
- Advanced analytics and reporting
- Multi-language support
- Official WhatsApp Business API integration
- Machine learning for message classification
- Advanced automation features
- Enterprise-grade features
Made with โค๏ธ by MiniMax Agent
Transform your WhatsApp automation dreams into reality with Baileyspy! ๐