Build Your Own QQ Bot
Introduction
Recently, I noticed that the WebUI of NapCatQQ has been fully developed and is quite suitable for beginners to get started. Therefore, I wrote this article.
This article only covers basic usage methods and may lack some advanced features. However, it's still necessary to understand the basics: command line, HTTP protocol, Docker, Python—this is not completely zero-level knowledge. (If you only want to use Webhook for notifications or use existing NoneBot plugins, there's no need to do Python programming.)
The tools used are NapCatQQ and NoneBot. The former runs QQ and connects to protocols like OneBot11, while the latter is a framework based on Python that calls the protocol. You can refer to the official documentation when encountering issues. (If you only want to use Webhook for notifications, setting up NapCatQQ alone is sufficient.)
Preparation
- A server, whether internal or external network.
- A QQ account as the QQ bot; it's not recommended to use your main account.
QQ can detect if plugins are being used, and your account might face issues such as forced logout, login restrictions, or freezing. Please assess based on your own situation before deciding whether to proceed. The author assumes no responsibility for any consequences arising from following this guide to build a bot.
NapCatQQ
Installation
NapCatQQ offers multiple installation methods, but since it's intended as a service, I recommend using the Docker Shell version: https://napneko.github.io/guide/boot/Shell#napcat-docker-linux-containerized-deployment nThe Docker container comes with NTQQ itself, so there's no need to install a separate version of QQ.
docker run -d \
-v /data/napcat/QQdata:/app/.config/QQ \\ # QQ data directory
-v /data/napcat/logs:/app/napcat/logs \\ # Log directory
-v /data/napcat/config:/app/napcat/config \\ # Configuration directory
-v /etc/localtime:/etc/localtime:ro \
--net=host \\ # It's recommended to use host network for connecting to the subsequent NoneBot
--name napcat \
--restart=always \
mlikiowa/napcat-docker:latest
At this point, accessing http://[IP]:6099/webui will show the NTQQ Web interface, where you can log in and set up. The login password can be found in the log file (default: napcat); it's recommended to change it after logging in.
Alternatively, you can check logs via docker logs napcat or scan a QR code to log in. When scanning, it's recommended to check "no further mobile verification required".
Enable HTTP Protocol
In the WebUI, go to Network Configuration -> New -> HTTP Server. You can freely choose the name, Host, and port. Message format is recommended to be Array, which actually works with String as well. It supports sending mixed text and image messages, and it's strongly advised to fill in a Token to prevent malicious requests.
After enabling, you can test it in API Debug -> HTTP or any other API testing tool you're comfortable with. API references: https://napcat.apifox.cn/
Token can be used in two ways:
- Add
Authorization: [Token]in the request header.
curl -X GET 'http://[IP]:3000/get_friend_list' -H 'Authorization: [Token]'
- Append
?access_token=[Token]to the URL.
curl -X GET 'http://[IP]:3000/get_friend_list?access_token=[Token]'
Using Webhook for Notifications
The most important interfaces here are sending private messages and sending group messages. You can find the corresponding APIs in API Debug -> HTTP, which also includes message construction functionality—quite simple.
Here’s an example of sending a private message:
curl -X POST 'http://[IP]:3000/send_private_msg' -H 'Content-Type: application/json' -H 'Authorization: [Token]' -d '{
"user_id": "[TargetQQ]",
"message": [
{
"type": "text",
"data": {
"text": "Hello World!"
}
},
{
"type": "face",
"data": {
"id": "63"
}
},
{
"type": "image",
"data": {
"file": "https://napneko.github.io/assets/newlogo.png"
}
}
]
}'

Some applications use shoutrrr as the Webhook implementation. Here’s an example configuration:
generic://[IP]:3000/send_private_msg?access_token=[Token]&template=json&titleKey=user_id&messageKey=message&@Content-Type=application/json&$user_id=[TargetQQ]
Some applications may already support the OneBot11 protocol. In that case, just enter http://[IP]:3000, the Token, and the target QQ number.
Nginx Reverse Proxy
If you have a domain name, you can refer to the following Nginx configuration example for NapCatQQ:
server {
listen 80;
listen [::]:80;
listen 443 ssl;
listen [::]:443 ssl;
server_name qq.example.cn;
access_log /var/log/nginx/access.qq.log;
error_log /var/log/nginx/error.qq.log;
location /webui {
proxy_pass http://127.0.0.1:6099$request_uri;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Real-PORT $remote_port;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
location /api {
proxy_pass http://127.0.0.1:6099$request_uri;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Real-PORT $remote_port;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
location /files {
proxy_pass http://127.0.0.1:6099$request_uri;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Real-PORT $remote_port;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
location / {
if ($request_method = POST) {
access_log /var/log/nginx/post.qq.log postdata;
}
proxy_pass http://127.0.0.1:3000$request_uri;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Real-PORT $remote_port;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
}
NoneBot
The documentation is already very comprehensive, so I won't repeat it here.