Binance 的公共 WebSocket API (2024-10-17)
API 基本信息
- 本篇所列出的 wss 接口的 base URL:
wss://ws-api.binance.com:443/ws-api/v3
- 如果使用标准443端口时遇到问题,可以使用替代端口9443。
- 现货测试网的 base URL 是
wss://testnet.binance.vision/ws-api/v3
。
- 每个到 base URL 的链接有效期不超过24小时,请妥善处理断线重连。
- Websocket 服务器每3分钟发送Ping消息。
- 如果Websocket服务器在10分钟之内没有收到Pong消息应答,连接会被断开。
- 当客户收到ping消息,必需尽快回复pong消息,同时payload需要和ping消息一致。
- 未经请求的pong消息是被允许的,但是不会保证连接不断开。对于这些pong消息,建议payload为空
- 响应中如有数组,数组元素以时间时间顺序排列,越早的数据越提前。
- 除非另有说明,所有与时间戳相关的字段均以UTC的毫秒为单位。
- 除非另有说明,所有字段名称和值都大小写敏感。
请求格式
请求必须在 text 帧 中以 JSON 格式发送,每帧一个请求。
请求示例:
{
"id": "e2a85d9f-07a5-4f94-8d5f-789dc3deb097",
"method": "order.place",
"params": {
"symbol": "BTCUSDT",
"side": "BUY",
"type": "LIMIT",
"price": "0.1",
"quantity": "10",
"timeInForce": "GTC",
"timestamp": 1655716096498,
"apiKey": "T59MTDLWlpRW16JVeZ2Nju5A5C98WkMm8CSzWC4oqynUlTm1zXOxyauT8LmwXEv9",
"signature": "5942ad337e6779f2f4c62cd1c26dba71c91514400a24990a3e7f5edec9323f90"
}
}
请求字段:
名称 | 类型 | 是否必需 | 描述 |
---|---|---|---|
id | INT / STRING / null | YES | 任意的 ID 用于匹配对请求的响应 |
method | STRING | YES | 请求函数名称 |
params | OBJECT | NO | 请求参数。如果没有参数可以省略 |
-
请求
id
是任意的。可以使用 UUID、顺次 ID 、当前时间戳等。 服务器不会以任何方式解释id
,只是在响应中回显它。可以在一个会话中自由重复使用 ID,不过请注意不要一次发送多个具有相同 ID 的请求,因为否则可能无法区分响应。
-
请求函数名称可以以显式版本为前缀,例如:
"v3/order.place"
-
params
的顺序不重要。
响应格式
响应在 text 帧 中以 JSON 格式返回,每帧一个响应。
成功响应示例:
{
"id": "e2a85d9f-07a5-4f94-8d5f-789dc3deb097",
"status": 200,
"result": {
"symbol": "BTCUSDT",
"orderId": 12510053279,
"orderListId": -1,
"clientOrderId": "a097fe6304b20a7e4fc436",
"transactTime": 1655716096505,
"price": "0.10000000",
"origQty": "10.00000000",
"executedQty": "0.00000000",
"cummulativeQuoteQty": "0.00000000",
"status": "NEW",
"timeInForce": "GTC",
"type": "LIMIT",
"side": "BUY",
"workingTime": 1655716096505,
"selfTradePreventionMode": "NONE"
},
"rateLimits": [
{
"rateLimitType": "ORDERS",
"interval": "SECOND",
"intervalNum": 10,
"limit": 50,
"count": 12
},
{
"rateLimitType": "ORDERS",
"interval": "DAY",
"intervalNum": 1,
"limit": 160000,
"count": 4043
},
{
"rateLimitType": "REQUEST_WEIGHT",
"interval": "MINUTE",
"intervalNum": 1,
"limit": 6000,
"count": 321
}
]
}
失败响应示例:
{
"id": "e2a85d9f-07a5-4f94-8d5f-789dc3deb097",
"status": 400,
"error": {
"code": -2010,
"msg": "Account has insufficient balance for requested action."
},
"rateLimits": [
{
"rateLimitType": "ORDERS",
"interval": "SECOND",
"intervalNum": 10,
"limit": 50,
"count": 13
},
{
"rateLimitType": "ORDERS",
"interval": "DAY",
"intervalNum": 1,
"limit": 160000,
"count": 4044
},
{
"rateLimitType": "REQUEST_WEIGHT",
"interval": "MINUTE",
"intervalNum": 1,
"limit": 6000,
"count": 322
}
]
}
响应字段:
名称 | 类型 | 是否必需 | 描述 |
---|---|---|---|
id |
INT / STRING / null |
YES | 与原来请求的ID一样 |
status |
INT | YES | 响应状态。请看 状态代码 |
result |
OBJECT / ARRAY | YES | 响应内容。请求成功则显示 |
error |
OBJECT | 错误描述。请求失败则显示 | |
rateLimits |
ARRAY | NO | 速率限制状态。请看 速率限制 |
状态代码
status
字段的状态代码与HTTP的状态代码相同。
一些常见状态代码:
200
代码指示成功响应。4XX
错误码用于指示错误的请求内容、行为、格式。问题在于请求者。400
– 错误码表示请求失败,请参阅error
了解原因。403
– 错误码表示违反 WAF 限制(Web应用程序防火墙)。409
– 错误码表示请求有一部分成功,一部分失败。请参阅error
了解更多详细。418
– 表示收到 429 后继续访问,于是被封了。429
– 错误码表示警告访问频次超限,即将被封IP。
5XX
错误码用于指示Binance服务侧的问题。- 重要:如果响应包含 5xx 状态码,并不一定意思请求失败。 执行状态为 unknown,请求可能实际成功。 请使用 query 函数确认状态。 建议建立一个新 WebSocket 连接用于确认状态。
有关错误代码和消息的列表,请参阅 Binance 的错误代码。
速率限制
连接数量限制
每IP地址、每5分钟最多可以发送300次连接请求。
速率限制基本信息
exchangeInfo
有包含与速率限制相关的信息。- 根据不同的间隔,有多种频率限制类型。
- 从响应中的可选
rateLimits
字段,能看到当前的频率限制状态。 - 当您超出未成交订单计数或者请求速率限制时,请求会失败并返回 HTTP 状态代码 429。
如何咨询频率限制
频率限制状态的响应可能如下所示:
{
"id": "7069b743-f477-4ae3-81db-db9b8df085d2",
"status": 200,
"result": {
"serverTime": 1656400526260
},
"rateLimits": [
{
"rateLimitType": "REQUEST_WEIGHT",
"interval": "MINUTE",
"intervalNum": 1,
"limit": 6000,
"count": 70
}
]
}
rate Limits
数组描述了受请求影响的所有当前的速率限制。
名称 | 类型 | 是否必须 | 描述 |
---|---|---|---|
rateLimitType | ENUM | YES | 频率限制类型: REQUEST_WEIGHT , ORDERS |
interval | ENUM | YES | 频率限制间隔: SECOND , MINUTE , HOUR , DAY |
intervalNum | INT | YES | 频率限制间隔乘数 |
limit | INT | YES | 每个间隔的请求限制 |
count | INT | YES | 每个间隔的当前使用情况 |
频率限制按间隔计算。
例如,1 MINUTE
间隔表示每分钟开始。
在 00:01:23.456 提交的请求计入 00:01:00 分钟的限制。
一旦 00:02:00 分钟开始,计数将再次重置为零。
其他间隔的行为方式类似。
例如,1 DAY
频率限制是在每天 00:00 UTC 重置,并且 10 SECOND
间隔重置为每分钟的 00、10、20...秒。
API 有多种频率限制间隔。 如果您用完了较短的间隔但较长的间隔仍然允许请求,您将不得不等待较短的间隔到期并重置。 如果你用完了更长的间隔,你将不得不等待那个间隔重置,即使较短的频率限制计数为零。
如何显示/隐藏频率限制信息
默认情况下,每个响应都包含 rateLimits
字段。
但是,频率限制信息可能非常大。
如果您对每个请求的详细频率限制状态不感兴趣,可以从响应中省略 rateLimits
字段。
-
请求中的可选
returnRateLimits
boolean 参数。使用
returnRateLimits
参数控制是否包含rateLimits
字段以响应单个请求。默认请求和响应:
{"id":1,"method":"time"}
{"id":1,"status":200,"result":{"serverTime":1656400526260},"rateLimits":[{"rateLimitType":"REQUEST_WEIGHT","interval":"MINUTE","intervalNum":1,"limit":6000,"count":70}]}
没有频率限制状态的请求和响应:
{"id":2,"method":"time","params":{"returnRateLimits":false}}
{"id":2,"status":200,"result":{"serverTime":1656400527891}}
-
连接 URL 中可选的
returnRateLimits
boolean 参数。如果您希望在默认情况下从所有响应中省略
rateLimits
,可以在 query string 中使用returnRateLimits
参数:wss://ws-api.binance.com:443/ws-api/v3?returnRateLimits=false
这将使通过此连接发出的所有请求的行为就像您已传了
"returnRateLimits":false
一样。如果您_想_查看特定请求的频率限制,您需要特定传
"returnRateLimits":true
参数。
注意: 如果您在响应中隐藏 rateLimits
字段,您的请求仍然还是会受到频率限制的。
IP 访问限制
- 每个请求都有一个特定的 权重,它会添加到您的访问限制中。
- 越消耗资源的接口, 比如查询多个交易对, 权重就会越大。
- 连接到 WebSocket API 会用到2个权重。
- 当前权重使用由
REQUEST_WEIGHT
频率限制类型指示。 - 请使用
exchangeInfo
请求来跟踪当前的重量限制。 - 权重是基于每个 IP 地址累积的,并由来自该地址的所有连接共享。
- 如果超多限制,客服端会收到
429
。- 这错误代码表示您有责任停止发送请求,不得滥用API。
- 响应会包含一个
retryAfter
字段,指示在什么时候您能重试。
- 屡次违反速率限制或者在收到429后未能退缩将导致自动 IP 封禁和断开连接。
- 被禁止 IP 地址的请求失败,状态为
418
。 retryAfter
字段表示解除禁令的timestamp。
- 被禁止 IP 地址的请求失败,状态为
- 频繁违反限制的封禁时间会逐渐延长,从最短2分钟到最长3天。
表示在1分钟内使用了(1200权重限制中的)70权重的成功响应:
{
"id": "7069b743-f477-4ae3-81db-db9b8df085d2",
"status": 200,
"result": [],
"rateLimits": [
{
"rateLimitType": "REQUEST_WEIGHT",
"interval": "MINUTE",
"intervalNum": 1,
"limit": 6000,
"count": 70
}
]
}
表示已被封禁且封禁将在 epoch 1659146400000
解锁的失败响应:
{
"id": "fc93a61a-a192-4cf4-bb2a-a8f0f0c51e06",
"status": 418,
"error": {
"code": -1003,
"msg": "Way too much request weight used; IP banned until 1659146400000. Please use WebSocket Streams for live updates to avoid bans.",
"data": {
"serverTime": 1659142907531,
"retryAfter": 1659146400000
}
},
"rateLimits": [
{
"rateLimitType": "REQUEST_WEIGHT",
"interval": "MINUTE",
"intervalNum": 1,
"limit": 6000,
"count": 2411
}
]
}
未成交订单计数
- 成功下单将更新
订单
速率限制类型。 - 被拒绝或不成功的订单可能会也可能不会更新
订单
速率限制类型。 - 请注意,如果您的订单一直顺利完成交易,您可以通过 API 持续下订单。更多信息,请参见 现货未成交订单计数规则。
- 使用
account.rateLimits.orders
请求来跟踪您在此时间间隔内下了多少订单。 - 如果超过此值,请求将失败,状态为
429
。- 此状态代码表示您应退出并停止向 API 滥发信息。
- 状态为
429
的响应会包含retryAfter
字段,用以指示何时可以重试请求。
- 这是按 每一个账户 维护的,并由该账户 的所有 API 密钥共享。
表示在10秒内下了12个订单和在24小时内下了4043个订单的成功响应:
{
"id": "e2a85d9f-07a5-4f94-8d5f-789dc3deb097",
"status": 200,
"result": {
"symbol": "BTCUSDT",
"orderId": 12510053279,
"orderListId": -1,
"clientOrderId": "a097fe6304b20a7e4fc436",
"transactTime": 1655716096505,
"price": "0.10000000",
"origQty": "10.00000000",
"executedQty": "0.00000000",
"cummulativeQuoteQty": "0.00000000",
"status": "NEW",
"timeInForce": "GTC",
"type": "LIMIT",
"side": "BUY",
"workingTime": 1655716096505,
"selfTradePreventionMode": "NONE"
},
"rateLimits": [
{
"rateLimitType": "ORDERS",
"interval": "SECOND",
"intervalNum": 10,
"limit": 50,
"count": 12
},
{
"rateLimitType": "ORDERS",
"interval": "DAY",
"intervalNum": 1,
"limit": 160000,
"count": 4043
},
{
"rateLimitType": "REQUEST_WEIGHT",
"interval": "MINUTE",
"intervalNum": 1,
"limit": 6000,
"count": 321
}
]
}
请求鉴权类型
- 每个函数都有自己的鉴权类型,鉴权类型决定了访问时应当进行何种鉴权。
- 鉴权类型会在本文档中各个函数名称旁声明。比如 下新的订单 (TRADE)。
- 如果没有特殊声明即默认为 NONE
鉴权类型 | API key | 签名 | 描述 |
---|---|---|---|
NONE | 公开市场数据 | ||
TRADE | required | required | 在交易所交易,下单和取消订单 |
USER_DATA | required | required | 私人账户信息,例如订单状态和交易历史 |
USER_STREAM | required | 管理用户数据流订阅 | |
MARKET_DATA | required | 历史市场数据访问 |
- 函数鉴权需要指定和验证有效的 API key。
- API key 可以在币安账户的 API 管理 页面创建。
- API key和密钥都是大小写敏感的。 切勿与任何人共享它们。 如果您发现您的账户有异常活动,请立即撤销所有keys并联系币安客服。
- API key 可以配置为仅允许访问某些类型的函数鉴权。
- 例如,可以拥有一个 API key 有
TRADE
的权限进行交易,同时使用另一个 API key 有USER_DATA
的权限来监控您的订单状态。 - 默认情况下,API key 不能
交易
。您需要先在 API 管理中开通交易权限。
- 例如,可以拥有一个 API key 有
TRADE
和USER_DATA
请求也称为SIGNED
请求。
SIGNED (TRADE 和 USER_DATA) 请求鉴权
- 为了授权请求,
SIGNED
请求必须带signature
参数。 - 请参考 签名请求示例(HMAC), 签名请求示例(RSA) 和 SIGNED 请求示例 (Ed25519) 理解如何计算签名。
时间同步安全
-
SIGNED
请求也必须发timestamp
参数,其值应当是请求发送时刻的 unix 时间戳(毫秒)。 -
还可以发送一个可选参数
recvWindow
,指定请求保持有效的时间。- 如果
recvWindow
未发送,默认为5000毫秒。 - 最大
recvWindow
为60000毫秒。
- 如果
-
请求处理逻辑:
if (timestamp < (serverTime + 1000) && (serverTime - timestamp) <= recvWindow) {
// 处理请求
} else {
// 拒绝请求
}
关于交易时效性 互联网状况并不完全稳定可靠,因此你的程序本地到币安服务器的时延会有抖动, 这是我们设置 recvWindow
的目所在。如果你从事高频交易,对交易时效性有较高的要求,可以灵活设置 recvWindow
以达到你的要求。
建议使用5000毫秒以下的 recvWindow
!
SIGNED 请求示例 (HMAC)
这是有关如何用 HMAC secret key 签署请求的分步指南。
示例 API key 和 secret key:
Key | Value |
---|---|
apiKey | vmPUZE6mv9SD5VNHk4HlWFsOr6aKE2zvsw0MuIgwCIPy6utIco14y7Ju91duEh8A |
secretKey | NhqPtmdSJYdKjVHjA7PZj4Mge3R5YNiP1e3UZjInClVN65XAbvqqM6A7H5fATj0j |
警告:请勿与任何人共享您的私钥。
示例密钥仅供参考。
请求示例:
{
"id": "4885f793-e5ad-4c3b-8f6c-55d891472b71",
"method": "order.place",
"params": {
"symbol": "BTCUSDT",
"side": "SELL",
"type": "LIMIT",
"timeInForce": "GTC",
"quantity": "0.01000000",
"price": "52000.00",
"newOrderRespType": "ACK",
"recvWindow": 100,
"timestamp": 1645423376532,
"apiKey": "vmPUZE6mv9SD5VNHk4HlWFsOr6aKE2zvsw0MuIgwCIPy6utIco14y7Ju91duEh8A",
"signature": "------ 未填写 ------"
}
}
如您所见,目前缺少 signature
参数。
第一步:创建签名内容
除了 signature
之外,获取所有请求 params
,然后按名称按字母顺序进行排序:
参数 | 取值 |
---|---|
apiKey | vmPUZE6mv9SD5VNHk4HlWFsOr6aKE2zvsw0MuIgwCIPy6utIco14y7Ju91duEh8A |
newOrderRespType | ACK |
price | 52000.00 |
quantity | 0.01000000 |
recvWindow | 100 |
side | SELL |
symbol | BTCUSDT |
timeInForce | GTC |
timestamp | 1645423376532 |
type | LIMIT |
将参数格式化为 参数=取值
对并用 &
分隔每个参数:
签名效载荷示例:
apiKey=vmPUZE6mv9SD5VNHk4HlWFsOr6aKE2zvsw0MuIgwCIPy6utIco14y7Ju91duEh8A&newOrderRespType=ACK&price=52000.00&quantity=0.01000000&recvWindow=100&side=SELL&symbol=BTCUSDT&timeInForce=GTC×tamp=1645423376532&type=LIMIT
第二步:计算签名
- 将
secretKey
解释为 ASCII 数据,将其用作 HMAC-SHA-256 的 key。 - 将签名有效负载签名为 ASCII 数据。
- 将 HMAC-SHA-256 输出编码为 hex string。
请注意,apiKey
、secretKey
和有效负载是大小写敏感的。
生成的签名值是不区分大小写的。
可以使用 OpenSSL 交叉检查您的签名算法实现:
$ echo -n 'apiKey=vmPUZE6mv9SD5VNHk4HlWFsOr6aKE2zvsw0MuIgwCIPy6utIco14y7Ju91duEh8A&newOrderRespType=ACK&price=52000.00&quantity=0.01000000&recvWindow=100&side=SELL&symbol=BTCUSDT&timeInForce=GTC×tamp=1645423376532&type=LIMIT' \
| openssl dgst -hex -sha256 -hmac 'NhqPtmdSJYdKjVHjA7PZj4Mge3R5YNiP1e3UZjInClVN65XAbvqqM6A7H5fATj0j'
cc15477742bd704c29492d96c7ead9414dfd8e0ec4a00f947bb5bb454ddbd08a
第三步:添加 signature
到 params
中
最后,使用生成的签名完成请求:
{
"id": "4885f793-e5ad-4c3b-8f6c-55d891472b71",
"method": "order.place",
"params": {
"symbol": "BTCUSDT",
"side": "SELL",
"type": "LIMIT",
"timeInForce": "GTC",
"quantity": "0.01000000",
"price": "52000.00",
"newOrderRespType": "ACK",
"recvWindow": 100,
"timestamp": 1645423376532,
"apiKey": "vmPUZE6mv9SD5VNHk4HlWFsOr6aKE2zvsw0MuIgwCIPy6utIco14y7Ju91duEh8A",
"signature": "cc15477742bd704c29492d96c7ead9414dfd8e0ec4a00f947bb5bb454ddbd08a"
}
}