Publish WordPress Post with Python Requests and REST API

11,518

Solution 1

I was able to solve this

  1. I installed & activated this plugin on my wordpress https://wordpress.org/plugins/application-passwords/

  2. follow the help text there and create your password string for your userid - assume it is mypassword123

  3. now do this on your terminal "admin:mypassword123" | base64

You will get a new password - say pwdabc123

  1. 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

you missed:

  • auth IS your jwt token, NOT base64 encode token
    • jwt token is got from POST /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

  1. edit .htaccess in wordpress root folder

added:

RewriteEngine on
RewriteCond %{HTTP:Authorization} ^(.*)
RewriteRule ^(.*) - [E=HTTP_AUTHORIZATION:%1]
  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 your admin
  • wordpress_password: here is your 123456

response:

{
    "token": "eyJ0eXAiOxxxxxxxxxxxxHYBhtuzc",
    "user_email": "[email protected]",
    "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:


more detail pls refer my Chinese posts:

Share:
11,518

Related videos on Youtube

Cl0udSt0ne
Author by

Cl0udSt0ne

Updated on May 15, 2022

Comments

  • Cl0udSt0ne
    Cl0udSt0ne 13 days

    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?

  • Alex R
    Alex R over 3 years
    For some people (me) this is only a partial solution... it leads to an issue with "Basic Authorization Headers missing" ... the quest for a working solution continues at wordpress.stackexchange.com/questions/328304/…
  • disruptive
    disruptive almost 3 years
    Does not work. Not sure if this ever worked, but not reproducible.