For the past few days I have been trying to automatically upload a Minecraft skin to Mojang's servers. I am able to successfully log into my skin account (and set the cookies appropriately). Without setting the cookies, when I go to https://minecraft.net/profile I get sent to the login page, but if I do set the cookies it brings me to the profile page as it should. I have looked through the POST data being sent many times when I upload a skin, but for the life of me I couldn't get it to work. I have tried many people's fixes, but yet I cannot find a fix that works.
public static void uploadSkin(BufferedImage image, boolean male, String username, String password){
try {
URL url = new URL("https://minecraft.net/login");
URLConnection con = url.openConnection();
HttpURLConnection http = (HttpURLConnection) con;
http.setRequestMethod("POST");
http.setDoOutput(true);
Map<String, String> arguments = new HashMap<>();
arguments.put("username", username);
arguments.put("password", password);
String s = "";
for(Map.Entry<String, String> entry : arguments.entrySet())s += "&" + URLEncoder.encode(entry.getKey(), "UTF-8") + "=" + URLEncoder.encode(entry.getValue(), "UTF-8");
s = s.replaceFirst("&", "");
byte[] out = s.getBytes(StandardCharsets.UTF_8);
int length = out.length;
http.setFixedLengthStreamingMode(length);
http.setRequestProperty("Content-Type", "application/x-www-form-urlencoded; charset=UTF-8");
http.setInstanceFollowRedirects(false);
http.connect();
OutputStream os = http.getOutputStream();
os.write(out);
String cooks = "";
String at = "";
for(int i = 0; i < 50; i++){
String headerName = http.getHeaderFieldKey(i);
String headerValue = http.getHeaderField(i);
if(headerName != null && headerValue != null)if("Set-Cookie".equalsIgnoreCase(headerName))cooks += ";" + headerValue.split(";")[0];
}
http.disconnect();
URL url3 = new URL("https://minecraft.net/profile");
URLConnection con3 = url3.openConnection();
HttpURLConnection http3 = (HttpURLConnection) con3;
http3.setRequestProperty("Cookie", cooks);
http3.connect();
for(int i = 0; i < 50; i++){
String headerName = http3.getHeaderFieldKey(i);
String headerValue = http3.getHeaderField(i);
if(headerName != null && headerValue != null)if("Set-Cookie".equalsIgnoreCase(headerName))if(headerValue.startsWith("PLAY_SESSION"))at = headerValue.split("AT=")[1].split("\"")[0];
}
http3.disconnect();
cooks = cooks.replaceFirst(";", "");
URL url2 = new URL("https://minecraft.net/profile/skin");
URLConnection con2 = url2.openConnection();
HttpURLConnection http2 = (HttpURLConnection) con2;
http2.setRequestProperty("Cookie", cooks);
http2.setRequestMethod("POST");
http2.setDoOutput(true);
Map<String, String> arguments2 = new HashMap<>();
arguments2.put("model", male ? "steve" : "3pxarm");
arguments2.put("authenticityToken", at);
String encoded = "PNG";
ByteArrayOutputStream bos = new ByteArrayOutputStream();
ImageIO.write(image, "png", bos);
byte[] imageBytes = bos.toByteArray();
BASE64Encoder encoder = new BASE64Encoder();
encoded += encoder.encode(imageBytes);
bos.close();
arguments2.put("skin", encoded);
String s2 = "";
for(Map.Entry<String, String> entry : arguments2.entrySet())s2 += "&" + URLEncoder.encode(entry.getKey(), "UTF-8") + "=" + URLEncoder.encode(entry.getValue(), "UTF-8");
s2 = s2.replaceFirst("&", "");
byte[] out2 = s2.getBytes(StandardCharsets.UTF_8);
int length2 = out2.length;
http2.setFixedLengthStreamingMode(length2);
http2.setRequestProperty("Content-Type", "multipart/form-data; charset=UTF-8;");
http2.setInstanceFollowRedirects(false);
http2.connect();
OutputStream os2 = http2.getOutputStream();
os2.write(out2);
InputStream is = http2.getInputStream();
Scanner sc = new Scanner(is, "UTF-8");
sc.useDelimiter("\\A");
while(sc.hasNext())System.out.println(sc.next());
sc.close();
http2.disconnect();
} catch (Exception e) {e.printStackTrace();}
}
I get this error when trying to run it
java.io.IOException: Server returned HTTP response code: 500 for URL: https://minecraft.net/profile/skin
at sun.net.www.protocol.http.HttpURLConnection.getInputStream(Unknown Source)
at sun.net.www.protocol.https.HttpsURLConnectionImpl.getInputStream(Unknown Source)
at net.supernatenetwork.snn.TTESTT.uploadSkin(TTESTT.java:104)
at net.supernatenetwork.snn.TTESTT.main(TTESTT.java:27)
Line 98 is "InputStream is = http2.getInputStream();" When I put the block for reading the HTML with the first http variable, it prints out nothing. I keep getting the error code 404. I do know that the error code 404 translates to file not found, but if I send no POST data it brings me to the profile page, so I am assuming it is linked to POST, since if I remove one of the fields in the first http, it gives me the same error (just with the login page and only if I try to get the data from that). The BufferedImage is not null, and it has data. I need it to be a BufferedImage because I need to edit it from a template before uploading it. After looking, I see that the content type for the skin is image/png, but I need it to be what I currently have it as there is multiple things going into the POST. My encoded variable starts with "PNG" because when I was debugging in Firefox, I saw that the skin starts with PNG (might just be a coincidence). I have tried it without the "PNG" but still had no luck. The image I am uploading is a PNG. Any help is appreciated! Thanks!
Edit: I got a different error (from the new code) which I put both where the old code and error was. I left the old notes untouched. Credit to gre_gor for helping me find out a few of the errors.
Edit 2: I know how to send things through post. I was just wondering how to upload a skin, which is different from what this was marked for being a duplicate.