Perl: Post automatically to WordPress blog with wp-poster.pl
I just wrote a Perl script that can automatically post to a WordPress blog. This could come very handy if you want to post a certain post at times. This could be anything, from a list of what you listen to every day, to your bookmarks, to your AdSense earnings, to the status of a server.
The code was tested on the latest version of Wordpress, WP 2.2 (actually, it was WordPress MU 1.2.1), but I suspect that it will work fine for almost every version. Three HTTP requests are required; one to log in, one to get some security-check-values (_wpnonce and temp_ID), and one to make the actual post. You need the LWP (lib-www-perl) package, which you probably already do have, and if you don’t, you can get it freely at cpan.
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 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 | #!/usr/bin/perl # Copyright 2007 Tim Johansson # http://timjoh.com/ # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA use strict; use LWP::UserAgent; # change this my $burl = 'http://timjoh.com/'; # don't forget the trailing slash my ( $usr, $pwd, $uid ) = ( 'USERNAME', 'PASSWORD', 1 ); # uid=1 if you are the initial administrator # ua my $ua = LWP::UserAgent->new; $ua->agent('wp-poster'); $ua->cookie_jar( {} ); # login my $req = HTTP::Request->new( POST => $burl . 'wp-login.php' ); $req->content_type('application/x-www-form-urlencoded'); $req->content( sprintf('log=%s&pwd=%s&wp-submit=1&redirect_to=wp-admin/',$usr,$pwd) ); my $res = $ua->request( $req ); # get _wpnonce and temp_id $req = HTTP::Request->new( POST => $burl . 'wp-admin/post-new.php' ); $res = $ua->request( $req ); if ( $res->is_success ) { if ( $res->content =~ m/"_wpnonce" value="([0-9a-f9]+)".*'temp_ID' value='(-?[0-9]+)'/s ) { # post $req = HTTP::Request->new( POST => $burl . 'wp-admin/post.php' ); $req->content_type('application/x-www-form-urlencoded'); $req->content( sprintf( '_wpnonce=%s' . '&user_ID=%d' . '&action=post&originalaction=post&post_type=post' . '&temp_ID=%s' . '&advanced_view=1' . #'&comment_status=open' . #'&ping_status=open' . #'&post_password=' . #'&post_name=' . #slug '&post_status=publish' . #'&edit_date=1' . '&post_title=%s' . '&content=%s' . '&post_pingback=1' . '&prev_status=draft' . '&publish=Publish' . '&referredby=redo' , $1, #nonce $uid, $2, #tempid 'test', #title 'Testar.' #content ) ); $res = $ua->request( $req ); &debug($res, 2); } else { &debug($res, 1); print $res->content } } else { &debug($res, 0) } sub debug { my ( $res, $id ) = @_; print $id, ': ', $res->status_line, "\n"; foreach ( $res->header_field_names ) { print $_, ': ', $res->header($_), "\n"; } return; } |
Please do not use this code for any malicious purpose. Spamming is evil.

Nice script, could be very useful sometime. I didn’t knew LWP could make POST-requests that simple but I’m ain’t that good at Perl.
Comment by Somerunce — May 30, 2007 @ 6:48 pm
Nice script, it could be very useful sometime. I didn’t know LWP could make POST-requests that simple but I’m not that good at Perl. However, nice job and continue doing this, ’cause I love it!
Comment by Somerunce — May 30, 2007 @ 6:51 pm
Somerunce, LWP is a very useful module for this. I’m glad it helped!
Comment by Tim — May 31, 2007 @ 8:50 pm
Hi! I think it doesn’t work with wp2.3
(I edited the url and password in the file)
see:
juanma@debian:~$ perl posting.pl
0: 503 Service Temporarily Unavailable
Connection: close
Date: Sun, 21 Oct 2007 17:51:32 GMT
Server: Apache/2.0.54 (Unix) PHP/4.4.7 mod_ssl/2.0.54 OpenSSL/0.9.7e mod_fastcgi/2.4.2 DAV/2 SVN/1.4.2
Vary: Accept-Encoding
Content-Length: 323
Content-Type: text/html; charset=iso-8859-1
Client-Date: Sun, 21 Oct 2007 17:49:38 GMT
Client-Peer: 208.113.162.10:80
Client-Response-Num: 1
Title: 503 Service Temporarily Unavailable
I don’t know what is the problem because I don’t know Perl… And, can you upgrade your code to support wp2.3 tags sistem?
Thanks to much.
Comment by Janzo — October 21, 2007 @ 6:00 pm
This was a very nice script (as all of your scripts are), but I was wondering if you write anything in c++. If you do I’d like to see some of your source files sometime.
Comment by Joe — November 2, 2007 @ 1:40 am
The gap between my initial understanding and your code may be too great, but here is my question.
Could this code be used to post newspaper headlines from one paper (available via RSS) into a Wordpress blog post every morning?
Thank you.
Comment by Danny — November 5, 2007 @ 5:58 pm
Hi
I really appreciated your code… Only one answer: how can I make the new posts appear as drafts? I tried changing the variables in the code as reported here http://www.nomorepasting.com/getpaste.php?pasteid=6494 but still no luck..
Hope you have a solution! I can’t find any reliable XML-RPC documentation, so I don’t know where I need to look.
Comment by Nicola Beghin — November 11, 2007 @ 8:33 pm
Hi Tim, This script is exactly what I’m after. I’m working on extending it to include Podcast publishing with Podpress. Unfortunatly I’ve run into a problem. It seems the “cookie jar” is broken. Basically on the very first request, Wordpress comes back saying that “cookies are not enabled”, so instead of authenticating, it’s going back to the login page. I’m trying to find a solution for it. I’m running WP 2.3.2.
Thanks!
Comment by Phil Massyn — January 5, 2008 @ 5:39 am
Hi,
i want to use this code but with my Wordpress version 2.3.1 it doesnt work, i hang on get _wpnonce and temp_id.
Do you have a newer version?
Thanks
Uwe
Comment by Uwe — January 11, 2008 @ 11:31 am
I have tried it on Wordpress 2.3.3, but unfortunately it doesn’t work. I run the script and get the result:
0: 302 Found
Cache-Control: no-cache, must-revalidate, max-age=0
Connection: close
Date: Sat, 01 Mar 2008 06:10:02 GMT
Pragma: no-cache
Location: http://dmz.mydomain/wp-login.php?redirect_to=%2Fwp-admin%2Fpost-new.php
Server: Apache/1.3.29 (Unix) PHP/4.3.9
Content-Type: text/html
Expires: Wed, 11 Jan 1984 05:00:00 GMT
Last-Modified: Sat, 01 Mar 2008 06:10:03 GMT
Client-Date: Sat, 01 Mar 2008 06:10:03 GMT
Client-Peer: 192.168.8.100:80
Client-Response-Num: 1
Client-Transfer-Encoding: chunked
X-Powered-By: PHP/4.3.9
What’s the problem with it?
Comment by jimlin — March 1, 2008 @ 6:10 am
[...] The past few days, I've found myself looking for different ways post entries that do not require a browser, or anything particularly GUI-based. I found a few different ideas to use perl to talk to WordPress via XML-RPC. I think the easiest way to use this would be to read in a marked up text file and post based on the mark up - much like how Blosxom works. But instead of saving the text file a certain directory, I would read in the file and then toss it. I could probably write something smarter, but I think this would be a good starting point for me. [...]
Pingback by A need to speak at nomaded's little corner — March 6, 2008 @ 3:13 am
Content-Length required
Comment by Joe — May 2, 2008 @ 3:33 pm
Thanks for the great script, Tim. What reference did you use for passing the POST parameters for the new posting? I can’t seem to find it anywhere… If possible, I’m looking to see if your code can be updated to include the new tagging feature from 2.3 — or at least categories.
Comment by Daniel Steinbock — May 22, 2008 @ 7:31 pm
To everyone trying to get it to work with newer versions of WordPress, I’m planning to start working on that soon. When the script is ready, I’ll make a new post about it and link there from here.
Comment by Tim — June 19, 2008 @ 10:02 am