Control Suno (https://suno.com) via real browser automation for AI music generation.
Prerequisites
- Suno account (Google login supported)
- Playwright installed in the browser
Workflow
1. Open Suno and log in
browser.open("https://suno.com")
2. Generate a song (Custom Mode + custom lyrics)
On Suno's Custom Mode page:
- Style Prompt: Style description (excluding lyrics)
- Lyrics: Lyric content (existing lyrics can be filled in)
3. Core operations
| Operation | Execution method |
|---|---|
| Open the creation page | browser.open("https://suno.com/create") |
| Fill in the style description | Input box ref lookup |
| Fill in the lyrics | Lyric input box ref lookup |
| Click generate | "Create" button |
| Wait for generation to complete | Poll to check status |
| Get the audio link | Parse the returned result |
Suno Custom Mode Prompt Template
G.E.M. 邓紫棋 style
Style Prompt:
G.E.M. style, powerful belting vocals, husky tones, R&B pop,
wide vocal range, emotional delivery, Cantonese/Mandarin singing,
breathy chorus, soulful ballads, 2000s-2020s C-pop diva energy
Chinese R&B ballad
Style Prompt:
Mid-tempo R&B pop ballad, emotional Mandarin vocals,
piano-driven, cinematic atmosphere, Jay Chou style melody,
nostalgic mood, rainy day atmosphere
Complete Custom Mode input template
[Verse]
(歌词内容)
[Chorus]
(副歌内容)
[Bridge]
(桥段)
[Outro]
(结尾)
---
Style: (风格描述)
Tempo: (BPM)
Mood: (情绪氛围)
Complete lyrics for "那天下雨了" (Suno format)
[Intro]
車子緩緩的開 你慢慢走來 我竟然看著你發呆
[Verse 1]
你尷尬Say個Hi 沒位坐下來
我想叫旁邊的離開
我車票都還在 心卻在窗外
因為你已下了站台
遠遠的看著你點點頭車已開
你一句話我爬窗離開
[Verse 2]
你證件掉了出來 我才明白
是那隔壁班的女孩
這麼多年彼此竟然沒認出來
是你變美還是我變帥
[Chorus]
你經過花就開 離開雨就來
這裡適合談個戀愛
如果我要一個夢幻的開場白
沒有比你更美的對白
[Bridge]
雪白的天空等待彩虹出現
你我的遇見是誰許的願
黑黑的夜空繁星變得耀眼
因為你出現在我身邊
[Verse 3]
你老家有點遠 但我有點閒
也許能陪你走一圈
把你的父母都見 吃幾口麻醬麵
也許還能打個幾圈
[Verse 4]
鄉間的麥芽田 害羞的臉
你提到多年前的暗戀
你剪下校園畢業冊的那一頁
是因為我在照片裡面
[Chorus]
雪白的天空等待彩虹出現
你我的遇見是誰許的願
黑黑的夜空繁星變得耀眼
因為你出現在我身邊
[Verse 5]
原來多年前在那個書店
借我課本的是你
原來看我被雨淋的那天
幫我撐傘也是你
[Bridge]
翹課的那一天 花落那一天
教室那間我已看見
消失的下雨天 我想再淋一遍
我應該對你唱著晴天
[Outro]
送你到家門外 我才明白
原來你早已有人疼愛
如果回到過去那一個下雨天
我會為了你把傘撐開
如果回到過去那一個下雨天
我絕不再 轉身離開
---
Style: Mid-tempo R&B pop ballad, nostalgic rainy day atmosphere, emotional Mandarin vocals, piano and strings arrangement, Jay Chou style melody, romantic and bittersweet mood
Tempo: 75 BPM
Mood: Nostalgic, emotional, romantic, bittersweet
Browser automation script template
#!/usr/bin/env python3
"""suno_create.py - 通过浏览器自动化在 Suno 生成歌曲"""
import asyncio
import sys
sys.path.insert(0, '/home/aa/clawd/skills/suno-skills/scripts')
from playwright.async_api import async_playwright
SUNO_URL = "https://suno.com/create"
async def create_song(style_prompt: str, lyrics: str = ""):
"""生成歌曲"""
async with async_playwright() as p:
browser = await p.chromium.launch(headless=False)
page = await browser.new_page()
# 打开创作页面
await page.goto(SUNO_URL)
await page.wait_for_load_state("networkidle")
# 查找 Custom Mode 开关并开启
custom_mode_toggle = page.locator("text=Custom Mode")
if await custom_mode_toggle.is_visible():
await custom_mode_toggle.click()
# 填入 Style Prompt
style_input = page.locator("textarea").first
await style_input.fill(style_prompt)
# 如果有歌词,填入歌词框
if lyrics:
# 查找歌词输入框(通常在 Style 下方)
lyrics_input = page.locator("textarea").nth(1)
await lyrics_input.fill(lyrics)
# 点击 Create 按钮
create_btn = page.locator("button:has-text('Create')")
await create_btn.click()
# 等待生成完成(轮询)
for _ in range(60): # 最多等待60次
await asyncio.sleep(10)
# 检查是否生成完成
status = await page.locator(".audio-container").count()
if status > 0:
print("✅ 歌曲生成完成!")
break
await browser.close()
if __name__ == "__main__":
# 示例:G.E.M. 风格《那天下雨了》
style = "G.E.M. style, powerful belting vocals, R&B pop, emotional Mandarin singing"
lyrics = """(歌词内容)"""
asyncio.run(create_song(style, lyrics))
Output artifacts
| Type | Description |
|---|---|
| Audio file | MP3/WAV format |
| Cover image | Automatically generated |
| Song link | Suno on-site URL |
Notes
- Free quota: 5 generations per day, more with a Pro subscription
- Copyright notice: Copyright of generated songs belongs to the Suno user
- Lyric length: It is recommended not to exceed 500 characters
- Generation time: Usually 1-3 minutes