217

I am using django-rest-framework. It provides an awesome Django admin style browsable self-documenting API. But anyone can visit those pages and use the interface to add data (POST). How can I disable it?

Community
  • 1
  • 1
iForests
  • 6,757
  • 10
  • 42
  • 75
  • Yes, users can login and use the API. But I don't want to show the admin-style browsable page to them. – iForests Aug 15 '12 at 07:25

4 Answers4

333

You just need to remove the browsable API renderer from your list of supported renderers for the view.

Generally:

REST_FRAMEWORK = {
    'DEFAULT_RENDERER_CLASSES': (
        'rest_framework.renderers.JSONRenderer',
    )
}

Per-view basis:

class MyView(...):
    renderer_classes = [renderers.JSONRenderer]

Aside:

In many cases I think it's a shame that folks would choose to disable the browsable API in any case, as it's a big aid to any developers working on the API, and it doesn't give them more permissions that they would otherwise have. I can see that there might be business reasons for doing so in some cases, but generally I'd consider it a huge asset. Although, in some cases there may be details shown (like the names of custom actions) that a non-public API may not want to expose.

See also the answer below for more detail about restricting the browsable API renderer to development.

Phoenix
  • 3,996
  • 4
  • 29
  • 40
Tom Christie
  • 33,394
  • 7
  • 101
  • 86
  • 47
    `it's a big aid to any developers working on the API`. Shouldn't they have settings files for development and production? In development enable the browsable API. – Jacob Valenta Feb 13 '14 at 16:39
  • 15
    @JacobValenta I *think* Tom Christie means that third-party developers using your API should be able to use the browsable API. – Dustin Wyatt Mar 25 '14 at 17:19
  • 2
    Yup, as per @DustinWyatt – Tom Christie Mar 27 '14 at 12:09
  • 7
    @TomChristie Tom, in my case view level permissions are preventing unauthorized users from seeing anything more then 401 in the browsable api with the exception of the Users view because I allow unauthorized POSTs to create new users. This causes the HTML form to be shown with autocompleted data that I don't want to expose. Is there an easy way to prevent this for unauthorized users short of making a custom template? – jeffjv Jun 26 '15 at 01:37
  • 1
    Just thought I would add many or most government customers explicitly ask for methods of discovery (like browsable REST API interfaces) to be completely disabled. I'm not saying it makes sense or that it's correct... it just is. – Ray Pendergraph Nov 02 '15 at 18:25
  • @RayPendergraph Sure. I'd probably be more moderate in my advice here these days. Either on or off both valid options. – Tom Christie Nov 04 '15 at 15:36
  • Take a look at https://github.com/encode/django-rest-framework/issues/1906 and https://github.com/encode/django-rest-framework/issues/1985 for risks about browsable API in production. – Vanni Totaro Feb 09 '18 at 14:03
  • Why is this the top-voted answer? He's concerned that `anyone can visit those pages and use the interface to add data (POST)`, and you're going to hide the browsable API? No, don't change the permissions, just leave them wide open and hope that no one finds out?! This is why the term "security through obscurity" exists. – Greg Schmit Oct 13 '19 at 21:33
  • You can disable on a per request basis by appending `&format=json` to your DRF url (for example to compare the payload size with vs without extras). – Max Goodridge May 31 '23 at 09:31
152

While the accepted answer to this question does answer the question as it was worded, I feel that it does not solve the actual issue at hand.

For completeness in this answer, disabling the browseable HTML api is done by removing it from the renderer classes like so:

REST_FRAMEWORK = {
    'DEFAULT_RENDERER_CLASSES': (
        'rest_framework.renderers.JSONRenderer',
    )
}

However, the actual issue the question alludes to is people being able to post to the API without authentication. While removing the form makes it less obvious, this answer does not protect the API endpoints.

At minimum, someone finds this question and is looking to protect the API from unauthenticated, or unauthorised POST submissions; the are looking to change the API Permissions

The following will set all endpoints to be read only unless the user is authenticated.

REST_FRAMEWORK = {
    'DEFAULT_PERMISSION_CLASSES': (
        'rest_framework.permissions.IsAuthenticatedOrReadOnly',
    )
}

If you would like to completely hide the API unless the user is logged in, you could also use IsAuthenticated.

FYI: This will also remove the form from the HTML browseable API as it responds to permissions. When an authenticated user logs in, the form will be available again.

Bonus Round:

Only enable the browseable HTML API in dev:

DEFAULT_RENDERER_CLASSES = (
    'rest_framework.renderers.JSONRenderer',
)

if DEBUG:
    DEFAULT_RENDERER_CLASSES = DEFAULT_RENDERER_CLASSES + (
        'rest_framework.renderers.BrowsableAPIRenderer',
    )

REST_FRAMEWORK = {
    'DEFAULT_PERMISSION_CLASSES': (
        'rest_framework.permissions.IsAuthenticatedOrReadOnly',
    ),
    'DEFAULT_RENDERER_CLASSES': DEFAULT_RENDERER_CLASSES
}
Routhinator
  • 3,559
  • 4
  • 24
  • 35
  • 2
    If you keep separate config files for local and production, you can just put this in your local.py settings file (just make sure to change the above from a tuple to a list): `REST_FRAMEWORK['DEFAULT_RENDERER_CLASSES'].append('rest_framework.renderers.BrowsableAPIRenderer')` – getup8 Nov 08 '19 at 06:40
  • This sentence "This will also remove the form from the HTML browseable API as it responds to permissions" is not completely true. As it will still be visible and expose the name of the view – user972014 Sep 22 '20 at 14:16
  • The form will not be there. The view will be. The statement is true @user972014 – Routhinator Nov 07 '20 at 21:04
  • @getup8 a nice solution, small mistake - can't append to tuple: REST_FRAMEWORK['DEFAULT_RENDERER_CLASSES'] += ('rest_framework.renderers.BrowsableAPIRenderer',) – Winters Nov 15 '21 at 04:49
10
 # For Production Only
 REST_FRAMEWORK = {
     'DEFAULT_RENDERER_CLASSES': (
         'rest_framework.renderers.JSONRenderer',
     )
 }

Just Add this to your settings.py should disable the Browsable API!

Greg Sadetsky
  • 4,863
  • 1
  • 38
  • 48
Syed Faizan
  • 958
  • 9
  • 19
4

In settings.py you can include a DEBUG flag like so:

DEBUG = env.bool("API_DEBUG", default=True)

Then you can set render behavior based on that flag if DEBUG is set to True or False:

if DEBUG:
    DEFAULT_RENDERER_CLASSES = (
        "rest_framework.renderers.JSONRenderer",
        "rest_framework.renderers.BrowsableAPIRenderer",
    )
else:
    DEFAULT_RENDERER_CLASSES = (
        "rest_framework.renderers.JSONRenderer",
    )

REST_FRAMEWORK = {
     'DEFAULT_RENDERER_CLASSES': DEFAULT_RENDERER_CLASSES,
 }

This way whenever the API is in debug mode it will show the browsable api and when it is not in debug mode it will render JSON only.

WMRamadan
  • 974
  • 1
  • 11
  • 25