I wrote a plugin that displays all products in a woocommerce store in admin settings option, now I want to add a link to download the products as CSV file.

The problem is, when I click the link I get a permission error saying I don't have permission to view this page.

Here's my code:

function extra_tablenav($which) {
    if ($which == "top") {
        echo '<h3 style="display:inline">'
        . __('These products are currently in the database:')
        . '</h3>' .
        '&nbsp;&nbsp;&nbsp;' .
        '<a href="' . admin_url('admin.php?page=download_csv.php') . '">' . __('Export to CSV') . '</a>';

How can I fix those permissions?


Do not point the URL to admin.php, use admin-post.php instead:

'<a href="' . admin_url( 'admin-post.php?action=print.csv' ) . '">'

In your plugin register a callback for that action:

add_action( 'admin_post_print.csv', 'print_csv' );

function print_csv()
    if ( ! current_user_can( 'manage_options' ) )

    header('Content-Type: application/csv');
    header('Content-Disposition: attachment; filename=example.csv');
    header('Pragma: no-cache');

    // output the CSV data

If you want to make the data available for anonymous users (not logged in), then register the callback again with:

add_action( 'admin_post_nopriv_print.csv', 'print_csv' );

… and remove the capability check from the function.

  • Just wanted to add for future reference that adding extra parameters to the URL can be accessed in the callback function by parsing the $_REQUEST variable. – eballeste Jun 29 '17 at 7:09
  • 1
    @eballeste Parsing $_GET, not $_REQUEST. Always use only the data from expected places. $_REQUEST includes POST and COOKIE data. – fuxia Jun 29 '17 at 7:11
  • Just adding for further clarity that although it is true that parsing the $_GET variable to parse the URL parameters is preferable to using the $_REQUEST variable, for security purposes, you should also be using nonces. Here's a useful link: tipsandtricks-hq.com/introduction-to-wordpress-nonces-5357 – eballeste Jun 29 '17 at 7:28

protected by Community Dec 16 '16 at 8:15

Thank you for your interest in this question. Because it has attracted low-quality or spam answers that had to be removed, posting an answer now requires 10 reputation on this site (the association bonus does not count).

Would you like to answer one of these unanswered questions instead?

Not the answer you're looking for? Browse other questions tagged or ask your own question.