目錄

解決 IG Markets 中使用 Python Requests POST 登入時遇到的 HTTP400 問題

問題

我嘗試使用 Python 的 Requests Package 登入 IG Markets 的 Rest API,結果回傳 HTTP 400:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
import requests
import pandas as pd

API_KEY = ...
IG_URL = "https://demo-api.ig.com/gateway/deal"
ACCOUNT_ID = ...

url = f"{IG_URL}/session"

session = requests.Session()

session.headers.update({
    "Content-Type": "application/json; charset=UTF-8",
    "Accept": "application/json; charset=UTF-8",
    "Version": "3",
    "X-IG-API-KEY": API_KEY,
    "IG-ACCOUNT-ID": ACCOUNT_ID
})

data = {
    "identifier": "XXX, 
    "password": "XXX" 
}

response = session.post(url, data=data, headers=None)

print(response.status_code)

但同樣的行為我用 IG Markets 網站Postman 軟體 測試都是正常…

IG Markets 網站 API 測試 Postman Rest API 測試

試錯

我東改西改、拔掉 header 中的各項元素又拔掉測試,但都沒有用。

怎麼可能會只有 Python 程式碼有問題!沒道理啊…難不成是 WSL 的問題?

ChatGPT 助攻

我把程式碼丟到 ChatGPT 中,並問它「上述這段程式會回傳 HTTP 400,請告訴我哪裡出問題了」

ChatGPT 的回覆
  1. 请求数据格式不正确:根据您的代码,您使用 data=data 参数将数据作为字典传递给 session.post 方法。然而,requests.post 方法需要将数据转换为 JSON 格式字符串,并将其作为 json 参数传递。要解决这个问题,您可以将 data 参数更改为 json=json.dumps(data),这将正确将数据转换为 JSON 格式。
    修正后的代码如下:
1
response = session.post(url, json=json.dumps(data), headers=None)
  1. 请求头缺少必要的信息:您在请求头中设置了一些必要的信息,例如 Content-TypeAcceptVersionX-IG-API-KEYIG-ACCOUNT-ID。然而,在您的代码中,您将 headers 参数设置为 None,这会导致请求头不被正确地发送。要解决这个问题,您可以直接将请求头传递给 session.post方法,而不是将 headers 参数设置为 None
    修正后的代码如下:
1
response = session.post(url, json=json.dumps(data), headers=session.headers)

请注意,您需要确保 API_KEYACCOUNT_ID 的值是正确的,并且与您使用的 API 服务商的要求相匹配。另外,如果上述修正后的代码仍然无法解决问题,请提供更多关于错误消息或其他相关的错误信息,以便我能够更准确地帮助您找到问题所在。

解決

原來是第 25 行的 response = session.post(url, data=data, headers=None) 中,不該用 data;改用 json 回傳即可。

修正後的完整程式碼:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
import requests
import pandas as pd

API_KEY = ...
IG_URL = "https://demo-api.ig.com/gateway/deal"
ACCOUNT_ID = ...

url = f"{IG_URL}/session"

session = requests.Session()

session.headers.update({
    "Content-Type": "application/json; charset=UTF-8",
    "Accept": "application/json; charset=UTF-8",
    "Version": "3",
    "X-IG-API-KEY": API_KEY,
    "IG-ACCOUNT-ID": ACCOUNT_ID
})

data = {
    "identifier": "XXX, 
    "password": "XXX" 
}

response = session.post(url, json=data, headers=None)

print(response.status_code)