Sign up ×
Stack Apps is a question and answer site for apps, scripts, and development with the Stack Exchange API. It's 100% free, no registration required.


Automatically adds a comment when closing a question, with the text taken directly from the close reason you chose, so that the OP can see why their question may be being downvoted, and improve it, before it is closed

It is disabled for Duplicate and Off-topic > Other since they already add a comment.

It's also disabled for Off-topic > Migrate since they don't really give much text.

The script automatically converts the HTML to Markdown, so links, italics etc. are also preserved.


First click

Second click


With a formatted close reason:

Installing: Firefox

  1. Install Greasemonkey
  2. Click to install the script

Installing: Chrome (with Tampermonkey)

  1. Click to install the script

Installing: Chrome (no Tampermonkey):

  1. Copy the code below and save it to a file called anything.user.js
  2. In Chrome, go to Tools > Extensions
  3. Open the folder you saved the script to and drag it on to the Extensions dialog.

Source code

// ==UserScript==
// @name        Auto-Add A Comment When Closing
// @description Automatically adds a comment with details of the close reason, so that the OP can see why their question may be being downvoted, and improve it, before it is closed (disabled for Duplicate, Off-topic > Migrate, and Off-topic > Other)
// @namespace
// @version     1.4
// @grant
// @match       http://**
// @match       http://**
// @match       http://**
// @match       http://**
// @match       http://**
// @match       http://**
// @match       http://**
// @match       http://**
// ==/UserScript==

// Hijacks all AJAX requests, and adds stateChanged() to the close popup
XMLHttpRequest.prototype.originalOpen =;
function hijackAJAX(method, url, async, username, password)
    if(url.indexOf("/close/popup") > 0)
        this.addEventListener("readystatechange", function(){ stateChanged(this); });
    this.originalOpen(method, url, async, username, password);
} = hijackAJAX;

// Receives an XHR's state changes, and runs popupLoaded() when the popup is open
function stateChanged(XHR)
    if(XHR.readyState === 4 && XHR.status === 200)
        setTimeout(popupLoaded, 1);

// Adds a submit listener to the close popup
function popupLoaded()
    var popup = document.getElementById('close-question-form');
    popup.addEventListener("submit", function(){ getText(popup); });

// On submit, receives a popup and gets the text for the close reason chosen
function getText(popup)
    var text, reasons;
    var reason = popup.elements["close-reason"].value;

    // Skip duplicates
    if(reason === "Duplicate")

    else if(reason === "OffTopic")
        reason = popup.elements["close-as-off-topic-reason"].value;
        reasons = document.getElementsByName("close-as-off-topic-reason");
        for(var i = 0; i < reasons.length; i++)
            if(reasons[i].value === reason)
                // Skip migrations & other
                if(reasons[i].getAttribute("data-subpane-name") === "migration" || typeof reasons[i].parentNode.parentNode.getElementsByClassName("off-topic-other-comment-container")[0] !== "undefined")

                text = reasons[i].parentNode.getElementsByClassName("action-name")[0].innerHTML;

        reasons = document.getElementsByName("close-reason");
        for(var i = 0; i < reasons.length; i++)
            if(reasons[i].value === reason)
                text = reasons[i].parentNode.getElementsByClassName("action-desc")[0].innerHTML;


// Receieves the close reason text, formats it in Markdown, and adds it to a new comment
function addComment(text)
    text = text.replace(/<span(.*)<\/span>/gim, "");                                // Remove [2] counter, showing how many other users voted on this reason
    text = text.trim();                                                             // Trim whitespace, newlines and tabs
    text = text.replace(/<b>|<\/b>/gim, "**");                                      // Bold
    text = text.replace(/<i>|<\/i>/gim, "*");                                       // Italics
    text = text.replace(/<a href="(.*?)"( target=".*?"){0,}( rel=".*?"){0,}>(.*?)<\/a>/gim, "[$4]($1)");    // Links (strip rel and target attrs if present)

    document.getElementsByName("comment")[0].innerText = text;
    setTimeout(submitComment, 250);

// After a short delay, submits the comment
function submitComment()
share|improve this question
I'm not sure I'd want the comment to be automatically added. Would it be possible for your script to stop just short of that, perhaps with the comment text pasted in the "Add Comment" box, ready to go? – Duncan Jul 2 '13 at 8:23
Yes. Remove the last function. That is what clicks the button. – Cody Guldner Jul 4 '13 at 11:15
This seriously needs more upvotes. – Kermit Dec 17 '13 at 15:41
The install links are dead ( has been down for more than a year). You could replace them with a raw link to github, or some other service. – Mogsdad Jul 7 at 13:23
@Kermit - Do you still use this? It's not working for me (firefox + tampermonkey). – Mogsdad Jul 7 at 14:32
@Mogsdad Nah. This was from a time when close reasons didn't hurt people's feelings – Kermit Jul 7 at 15:16
@Mogsdad I've updated the links to GreasyFork. Unsure if there's been a code change on SE to break it, but if so it should only require a small amount of effort from a qualified wizard to fix ;) – Danny Beckett Jul 8 at 10:21

You must log in to answer this question.

Browse other questions tagged .