'Publish WordPress Post with Python Requests and REST API
I try to publish post to WordPress blog with python requests and rest api by following code:
auth = 'Basic ' + str(base64.b64encode(b'admin:123456'), 'utf-8')
headers = {'Authorization': auth}
body = {'title': 'Hello World'}
r = requests.post('wp-json/wp/v2/posts', headers=headers, data=body)
and always got 401 error:
>>> r.text
'{"code":"rest_cannot_create","message":"Sorry, you are not allowed to create posts as this user.","data":{"status":401}}'
I'm pretty sure that the account admin and password is correct and has administrator role, Did I miss anything?
Solution 1:[1]
I was able to solve this
I installed & activated this plugin on my wordpress https://wordpress.org/plugins/application-passwords/
follow the help text there and create your password string for your userid - assume it is mypassword123
now do this on your terminal "admin:mypassword123" | base64
You will get a new password - say pwdabc123
- Code looks like
url_srcdest = "http://example.com/wp-json/wp/v2/pages/"
headers = {'Content-Type': 'application/json',
'Authorization': 'Basic pwdabc123',
'Username': '<your username>',
'Password':'pwdabc123'}
data = \
{
"title":"Testing via API via Python",
"content":"tEST CONTENT OF THE THIS TEST PAGE via PYTHON",
"status": "publish"
}
response = requests.post(url_srcdest, data=json.dumps(data), headers=headers)
Solution 2:[2]
you missed:
auth
IS yourjwt token
, NOTbase64 encode token
jwt token
is got fromPOST /wp-json/jwt-auth/v1/token
How to get jwt token
?
prerequisite
installed jwt plugin
install and enable WordPress plugin:
wordpress server enable jwt authorization
for example, my wordpress server is: CentOS
- edit
.htaccess
in wordpress root folder
added:
RewriteEngine on
RewriteCond %{HTTP:Authorization} ^(.*)
RewriteRule ^(.*) - [E=HTTP_AUTHORIZATION:%1]
- edit
wp-config.php
add:
define('JWT_AUTH_SECRET_KEY', 'anyValueIsOk');
anyValueIsOk
: change to yours, any value is OK- just do NOT tell other, ^_^
- Remember
service php-fpm restart
after edit php file
POST /wp-json/jwt-auth/v1/token
to generate jwt token
call REST api to generate jwt token
POST https://www.yourWebsite.com/wp-json/jwt-auth/v1/token
{
"username": "wordpress_username",
"password": "wordpress_password"
}
wordpress_username
: here is youradmin
wordpress_password
: here is your123456
response:
{
"token": "eyJ0eXAiOxxxxxxxxxxxxHYBhtuzc",
"user_email": "xxx@yyy.com",
"user_nicename": "xxx",
"user_display_name": "xxx"
}
eyJ0eXAiOxxxxxxxxxxxxHYBhtuzc
: is the jwt token, which is what your need
[Optional] validate token is valid
POST https://www.crifan.com/wp-json/jwt-auth/v1/token/validate
headers:
Authorization: Bearer eyJ0eXAiOxxxxxxxxxxxxHYBhtuzc
response:
{
"code": "jwt_auth_valid_token",
"data": {
"status": 200
}
}
Additionally: use python call wordpress REST api to create posts
code:
import requests
your_jwt_token = "xxx"
curHeaders = {
"Authorization": "Bearer %s" % your_jwt_token,
"Content-Type": "application/json",
"Accept": "application/json",
}
categoryIdList = []
tagIdList = []
if categoryNameList:
# ['Mac']
categoryIdList = self.getTaxonomyIdList(categoryNameList, taxonomy="category")
# category nameList=['Mac'] -> taxonomyIdList=[1374]
if tagNameList:
# ['??', 'GPU', 'pmset', '????']
tagIdList = self.getTaxonomyIdList(tagNameList, taxonomy="post_tag")
# post_tag nameList=['??', 'GPU', 'pmset', '????'] -> taxonomyIdList=[1367, 13224, 13225, 13226]
postDict = {
"title": title, # '????Mac??pmset??GPU??????'
"content": content, # '<div>\n ???\n </div>\n <div>\n ?????Mac Pro 2018??????????\n </div>\n <div>\n ???...performance graphic cards\n </li>\n </ul>\n </ul>\n </ul>\n <div>\n <br/>\n </div>'
# "date_gmt": dateStr,
"date": dateStr, # '2020-08-17T10:16:34'
"slug": slug, # 'on_mac_pmset_is_used_set_gpu_graphics_card_switching_mode'
"status": status, # 'draft'
"format": postFormat, # 'standard'
"categories": categoryIdList, # [1374]
"tags": tagIdList, # [1367, 13224, 13225, 13226]
# TODO: featured_media, excerpt
}
yourHost = 'https://www.crifan.com'
createPostUrl = yourHost + "/wp-json/wp/v2/posts" # 'https://www.crifan.com/wp-json/wp/v2/posts'
resp = requests.post(
createPostUrl,
# proxies=self.requestsProxies,
headers=curHeaders,
# data=json.dumps(postDict),
json=postDict, # internal auto do json.dumps
)
response example:
{
"id": 70410,
"date": "2020-02-27T21:11:49",
"date_gmt": "2020-02-27T13:11:49",
"guid": {
"rendered": "https://www.crifan.com/?p=70410",
"raw": "https://www.crifan.com/?p=70410"
},
"modified": "2020-02-27T21:11:49",
"modified_gmt": "2020-02-27T13:11:49",
"password": "",
"slug": "mac_pip_change_source_server_to_spped_up_download",
"status": "draft",
"type": "post",
"link": "https://www.crifan.com/?p=70410",
"title": {
'raw": "?????Mac??pip????????",
"rendered": "?????Mac??pip????????"
},
"content": {
...
}
}
Note:
- latest full code:
- wordpress official doc: Create a Post
more detail pls refer my Chinese posts:
Solution 3:[3]
I just use requests
as described here, along with the application password:
import requests
r = requests.get('https://example-wp.com/wp-json/', auth=('username', 'APPLICATIONPASSWORD'))
r.status_code
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
Solution | Source |
---|---|
Solution 1 | Ruvee |
Solution 2 | crifan |
Solution 3 | Muminpappa |