6

I might be trying to do something impossible or really hard, but I wanted to try it out anyway. I have been working on writing a program that can automatically downvote Stack Overflow posts for me.

So, my logical first step was to find out what went on behind the scenes when I pressed the downvote button. I used a HTTP network analyzer to see how the browser communicates to the server that I want to downvote. This is what it showed me.

Downvote details

Then I figured I should be able to remotely downvote it if I write a C# program that sends an HTTP request identical to the one I sent when I pressed the downvote button. So I came up with this:

WebRequest req = WebRequest.Create("http://stackoverflow.com/posts/3905734/vote/3");
req.Method = "POST";
req.ContentType = "application/x-www-form-urlencoded";
req.ContentLength = 37;

req.Headers.Add("Request", "POST /posts/3905734/vote/3 HTTP/1.1");
req.Headers.Add("Accept", "application/json, text/javascript, */*; q=0.01");
req.Headers.Add("X-Requested-With", "XMLHttpRequest");
req.Headers.Add("Referer", "http://stackoverflow.com/questions/3905734/how-to-send-100-000-emails-weekly");
req.Headers.Add("Accept-Language", "en-us");
req.Headers.Add("Accept-Encoding", "gzip, deflate");
req.Headers.Add("User-Agent", "Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; WOW64; Trident/5.0; MAAU)");
req.Headers.Add("Host", "stackoverflow.com");
req.Headers.Add("Connection", "Keep-Alive");
req.Headers.Add("Cache-Control", "no-cache");
req.Headers.Add("Cookie", "__utmc=140029553; __utma=140029553.1661295586.1330352934.1331336368.1331402208.44; __utmz=140029553.1331159433.33.7.utmcsr=meta.stackoverflow.com|utmccn=(referral)|utmcmd=referral|utmcct=/users/153008/cody-gray; __qca=P0-1737884911-1330352934366; usr=t=TJUTES9CakOu&s=f3MgHSwW2EWk; km_ai=91003; km_uq=; km_lv=x; km_ni=91003; __utmb=140029553.17.10.1331402208");

var requestMessage = Encoding.UTF8.GetBytes("fkey=abfd538253d7ca1e988f306ea992eda0");
var strm = req.GetRequestStream();
strm.Write(requestMessage, 0, requestMessage.Length);
strm.Close();

var rep = req.GetResponse();
strm = rep.GetResponseStream();
var rdr = new StreamReader(strm);
string responseFromServer = rdr.ReadToEnd();
Console.WriteLine(responseFromServer);
rdr.Close();
strm.Close();
Console.Read();

There were some headers that it would not let me write. For the headers Accept, Referer, User-Agent and Connection, it threw an error like this:

This header must be modified using the appropriate property or method.

and the Host header caused this error:

The 'Host' header cannot be modified directly.

I just commented out the headers that were causing trouble, optimistically hoping that it would still work anyway, but I got back this message from the server

{"Success":false,"Warning":false,"NewScore":0,"Message":"","Refresh":false}

The "Success":false seemed to indicate that it was not successful in downvoting the post, and I went to the page and it had the same vote count as it did before I ran the program. In other words, my program didn't work.

Does anybody know if I'm on the right path, what I can do to make it work, or if it's even possible to make it work?

Peter Olson
  • 139,199
  • 49
  • 202
  • 242
  • 1
    I have very little knowledge of this sort of thing, but just out of curiosity, do you know if the fkey is randomly generated (being used for a security measure or something)? Or am I way off on that? Also, for the record, this is the best question I've seen all day. :) – Elliot Bonneville Mar 10 '12 at 18:37
  • 13
    Is this something you should really be doing? Even worse, is it something you should really be _sharing_ how to do? – M.Babcock Mar 10 '12 at 18:39
  • 1
    @M.Babcock We're all programmers here, somebody's bound to think up way to programatically manipulate this site sooner or later. – Peter Olson Mar 10 '12 at 18:43
  • Since the Host is where it was originated from (if I remember correctly) I doubt this is something that you will be able to set directly and it looks like it may be something that SO is using to keep you from doing what you are wanting to do. – Jared Mar 10 '12 at 18:44
  • 1
    Sort of spoils it for a lot of people, dont understand why anyone would up vote such a poor question. – Lloyd Mar 10 '12 at 18:44
  • @ElliotBonneville I think the `fkey` is per-user. I've inspected votes more than once and the `fkey` is always the same for me. – Peter Olson Mar 10 '12 at 18:45
  • Automatically downvoting posts sounds scary to me! Why would you want to do this? – Olivier Jacot-Descombes Mar 10 '12 at 18:46
  • @PeterOlson - Agreed, and I know it _is_ possible. The problem I have is that the question is potentially destructive. It probably would have gone without criticism if you didn't explicitly say what you're trying to achieve. – M.Babcock Mar 10 '12 at 18:47
  • @OlivierJacot-Descombes For fun, of course! If you prefer, you could also automatically upvote them. – Peter Olson Mar 10 '12 at 18:48
  • 1
    Peter you are trying to modify some restricted headers. Take a look at this http://stackoverflow.com/questions/239725/c-sharp-webrequest-class-and-headers – Nathan Mar 10 '12 at 18:49
  • Is an answer acceptable when `WebbrowserControl` is part of the solution? –  Mar 10 '12 at 19:30
  • You probably must send the correct header. Listen to your error messages, there is a special method to set it (not Headers.Add, I don't know what it's called). Also, you have to get the page once and retrieve the right cookies and keys to post along. And then, you have to log in beforehand of course (also setting a cookie). – jdm Jan 04 '13 at 00:31

1 Answers1

26

You might not consider this an answer, but I do; what you are trying to do is considered abuse of the system. We do not provide an API for that for many reasons, and trying to reverse engineer something that is not part of a published API is ... obnoxious.

Thanks for posting your security cookies. I will thus hit a button to log you out of SE, to protect your account from abuse. You will be able to log back in as normal.

We reserve the right to be frankly downright childish and puerile if you insist on trying to abuse the system; we're always happy to introduce extra hoops and hurdles, randomly change the API, etc if we believe you are trying to do nasty things. Or just suspend the account or block network access.

Allow me to summarise: we don't really want you doing this.

Marc Gravell
  • 1,026,079
  • 266
  • 2,566
  • 2,900
  • 1
    +1 Not the answer I wanted, of course, but I'm kind of excited to get an "official" answer like this. – Peter Olson Mar 10 '12 at 20:02
  • @Peter as noted, I've hit the "log out everywhere" button - this is purely for your protection - if you find yourself logged out it is not because I've done anything to your account. – Marc Gravell Mar 10 '12 at 20:05
  • Got it, and I guess I should say, thank you. – Peter Olson Mar 10 '12 at 20:07
  • 1
    Marc - People with high 'Reputations' abuse the system all the time. They downvote without bothering to leave a reason. I believe I've become the target of a user because all of a sudden every question I post gets a downvote. I've even had other users with good 'reputations' question the downvoting on my questions. Why don't you require people to explain the reason for the downvote. If the system is meant to improve the quality of the questions, then it is failing since the posters can have no indication as to what their mistake is. - Lee – Lee Loftiss Mar 22 '12 at 13:43
  • @Lee that is unrelated to *this* question, but what you ask has been discussed previously on meta. You are not being targeted by an individual user (I've checked). Re "every question"; I've checked your last 10 posts (q&a), 2 have downvotes, one of those also has several "not a real question" votes, and I agree: there's not enough info there to even start to answer that (red5). The VB one is trickier, however; **in most cases**, the current approach is less harmful; most downvotes *are* for a very obvious reason, or a reason is specified. That is maybe not *always* the case, but... – Marc Gravell Mar 22 '12 at 13:52
  • 1
    *trying to reverse engineer something that is not part of a published API is ... obnoxious* [I...](http://meta.stackexchange.com/a/63420/131541) um... [well...](http://stackapps.com/questions/3033/thirdplace-javascript-chat-library) *gulps* – Josh Mar 28 '12 at 21:21
  • 3
    @Josh our sense of protection between chat and q&a is somewhat different – Marc Gravell Mar 28 '12 at 22:50